BlitzMax/模块/BASIC/反射
BlitzMax 为运行时反射提供有限支持。
使用反射,程序可以在运行时“检查”对象和类型。你可以确定对象或类型中包含的字段和方法,设置和获取对象字段并调用对象方法。
要使用反射,你首先需要一个 TTypeId 对象。TTypeId 对象对应于 BlitzMax 用户定义的类型,程序中的每个用户定义的类型都有一个 TTypeId 对象。还有一些 TTypeId 对象用于“基本”类型 - 字节、短整型、整型、长整型、浮点型、双精度型和字符串。TTypeId 对象由TTypeId.ForName 和TTypeId.ForObject 函数返回。
获得 TTypeId 对象后,可以使用EnumFields 和EnumMethods 方法检查用户定义类型的字段和方法。这些方法返回TField 和TMethod 对象,它们描述了类型内的字段和方法。例如
Strict Type TMyType Field x,y,z End Type Local id:TTypeId=TTypeId.ForName( "TMyType" ) For Local fld:TField=EachIn id.EnumFields() Print fld.Name()+":"+fld.TypeId().Name() Next
这个简单的程序将打印“x:Int”、“y:Int”和“z:Int” - TMyType 内字段的名称和类型。请注意,这是在没有实际创建新的 TMyType 的情况下完成的。
以下示例设置了对象的字段
Strict Type TMyType Field x,y,z End Type Local obj:TMyType=New TMyType Local id:TTypeId=TTypeId.ForObject( obj ) For Local fld:TField=EachIn id.EnumFields() fld.Set obj,String( Rand(10) ) Next Print obj.x+","+obj.y+","+obj.z
在这种情况下,我们需要一个实际的 TMyType 实例,否则我们将无法设置字段!另外,我们使用了 TTypeId.ForObject 而不是 TTypeId.ForName 来获取一个 TTypeId。虽然在这种情况下可以使用 TTypeId.ForName 来达到相同的结果,但一般情况下我们可能不知道对象的具体类型,因此我们也不知道其类型名称。
还要注意,实际设置字段的代码使用的是 String( Rand(10) )。这是因为Set 方法接受一个对象 - 但我们的字段是整型!BlitzMax 反射通过使用字符串来表示数值类型来解决这个问题。相同的规则适用于Get 方法。任何数值字段都将作为字符串返回,如果需要,你必须将其转换为相应的类型。
最后,让我们调用对象方法
Strict Type TMyType Method Update( t# ) Print "TMyType.Update:"+t End Method End Type Local obj:TMyType=New TMyType Local id:TTypeId=TTypeId.ForObject( obj ) Local update:TMethod=id.FindMethod( "Update" ) update.Invoke obj,[String( .25 )]
这个示例使用FindMethod 来定位类型方法,使用Invoke 来调用它。方法的参数包含在一个对象数组中,同样,浮点型参数也被转换为字符串。
除了 TTypeId、TField 和 TMethod 类型之外,BlitzMax 反射模块还声明了一些全局 TTypeId 对象
- ByteTypeId
- ShortTypeId
- IntTypeId
- LongTypeId
- FloatTypeId
- DoubleTypeId
- StringTypeId
- ObjectTypeId
这些可以代替相应的 TTypeId.ForName 调用。例如,TTypeId.ForName( "Int" ) 和IntTypeId 将返回同一个对象。
Global ByteTypeId:TTypeId=New TTypeId.Init( "Byte",1 )
描述: 基本字节类型
Global ShortTypeId:TTypeId=New TTypeId.Init( "Short",2 )
描述: 基本短整型类型
Global IntTypeId:TTypeId=New TTypeId.Init( "Int",4 )
描述: 基本整型类型
Global LongTypeId:TTypeId=New TTypeId.Init( "Long",8 )
描述: 基本长整型类型
Global FloatTypeId:TTypeId=New TTypeId.Init( "Float",4 )
描述: 基本浮点型类型
Global DoubleTypeId:TTypeId=New TTypeId.Init( "Double",8 )
描述: 基本双精度型类型
Global StringTypeId:TTypeId=New TTypeId.Init( "String",4,bbRefStringClass() )
描述: 基本字符串类型
Global ObjectTypeId:TTypeId=New TTypeId.Init( "Object",4,bbRefObjectClass() )
描述: 基本对象类型
Global ArrayTypeId:TTypeId=New TTypeId.Init( "Null[]",4,bbRefArrayClass() )
描述: 基本数组类型
类型成员 - 字段或方法。
- 名称
- TypeId
- 元数据
Method Name$()
描述: 获取成员名称
Method TypeId:TTypeId()
描述: 获取成员类型
Method MetaData$( key$="" )
描述: 获取成员元数据
类型字段
- 获取
- GetInt
- GetLong
- GetFloat
- GetDouble
- GetString
- 设置
- SetInt
- SetLong
- SetFloat
- SetDouble
- SetString
Method Get:Object( obj:Object )
描述: 获取字段值
Method GetInt:Int( obj:Object )
描述: 获取整型字段值
方法 GetLong:Long( obj:Object )
描述: 获取长整型字段值
方法 GetFloat:Float( obj:Object )
描述: 获取浮点型字段值
方法 GetDouble:Double( obj:Object )
描述: 获取双精度浮点型字段值
方法 GetString$( obj:Object )
描述: 获取字符串字段值
方法 Set( obj:Object,value:Object )
描述: 设置字段值
方法 SetInt( obj:Object,value:Int )
描述: 设置整型字段值
方法 SetLong( obj:Object,value:Long )
描述: 设置长整型字段值
方法 SetFloat( obj:Object,value:Float )
描述: 设置浮点型字段值
方法 SetDouble( obj:Object,value:Double )
描述: 设置双精度浮点型字段值
方法 SetString( obj:Object,value$ )
描述: 设置字符串字段值
类型 方法
- ArgTypes
- Invoke
方法 ArgTypes:TTypeId[]()
描述: 获取方法参数类型
方法 Invoke:Object( obj:Object,args:Object[] )
描述: 调用方法
类型 id
- 名称
- 元数据
- SuperType
- ArrayType
- ElementType
- ExtendsType
- DerivedTypes
- NewObject
- Fields
- 方法
- FindField
- FindMethod
- EnumFields
- EnumMethods
- NewArray
- ArrayLength
- ArrayDimensions
- GetArrayElement
- SetArrayElement
- ForName
- ForObject
- EnumTypes
Method Name$()
描述: 获取类型的名称
Method MetaData$( key$="" )
描述: 获取类型元数据
方法 SuperType:TTypeId()
描述: 获取父类型
方法 ArrayType:TTypeId(dims:Int = 1)
描述: 获取数组类型
方法 ElementType:TTypeId()
描述: 获取元素类型
方法 ExtendsType( typeId:TTypeId )
描述: 判断类型是否继承自某个类型
方法 DerivedTypes:TList()
描述: 获取派生类型列表
方法 NewObject:Object()
描述: 创建一个新对象
方法 Fields:TList()
描述: 获取字段列表
信息: 仅返回该类型中声明的字段,不包括父类型中的字段。
方法 Methods:TList()
描述: 获取方法列表
信息: 仅返回该类型中声明的方法,不包括父类型中的方法。
方法 FindField:TField( name$ )
描述: 按名称查找字段
信息: 在类型层次结构中搜索名为 name 的字段。
方法 FindMethod:TMethod( name$ )
描述: 按名称查找方法
信息: 在类型层次结构中搜索名为 name 的方法。
方法 EnumFields:TList( list:TList=Null )
描述: 枚举所有字段
信息: 返回类型层次结构中所有字段的列表
方法 EnumMethods:TList( list:TList=Null )
描述: 枚举所有方法
信息: 返回类型层次结构中所有方法的列表 - TODO: 处理覆盖方法!
方法 NewArray:Object( length, dims:Int[] = Null )
描述: 创建一个新数组
方法 ArrayLength( array:Object, dim:Int = 0 )
描述: 获取数组长度
方法 ArrayDimensions:Int( array:Object )
描述: 获取维度数量
方法 GetArrayElement:Object( array:Object,index )
描述: 获取数组元素
方法 SetArrayElement( array:Object,index,value:Object )
描述: 设置数组元素
函数 ForName:TTypeId( name$ )
描述: 按名称获取类型
函数 ForObject:TTypeId( obj:Object )
描述: 按对象获取类型
函数 EnumTypes:TList()
描述: 获取所有类型的列表