跳转到内容

BlitzMax/模块/BASIC/反射

来自维基教科书,开放的书籍,为开放的世界

BlitzMax 为运行时反射提供有限支持。

使用反射,程序可以在运行时“检查”对象和类型。你可以确定对象或类型中包含的字段和方法,设置和获取对象字段并调用对象方法。

要使用反射,你首先需要一个 TTypeId 对象。TTypeId 对象对应于 BlitzMax 用户定义的类型,程序中的每个用户定义的类型都有一个 TTypeId 对象。还有一些 TTypeId 对象用于“基本”类型 - 字节、短整型、整型、长整型、浮点型、双精度型和字符串。TTypeId 对象由TTypeId.ForNameTTypeId.ForObject 函数返回。

获得 TTypeId 对象后,可以使用EnumFieldsEnumMethods 方法检查用户定义类型的字段和方法。这些方法返回TFieldTMethod 对象,它们描述了类型内的字段和方法。例如

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 将返回同一个对象。

全局变量

[编辑 | 编辑源代码]

ByteTypeId

[编辑 | 编辑源代码]

Global ByteTypeId:TTypeId=New TTypeId.Init( "Byte",1 )

描述: 基本字节类型

ShortTypeId

[编辑 | 编辑源代码]

Global ShortTypeId:TTypeId=New TTypeId.Init( "Short",2 )

描述: 基本短整型类型

IntTypeId

[编辑 | 编辑源代码]

Global IntTypeId:TTypeId=New TTypeId.Init( "Int",4 )

描述: 基本整型类型

LongTypeId

[编辑 | 编辑源代码]

Global LongTypeId:TTypeId=New TTypeId.Init( "Long",8 )

描述: 基本长整型类型

FloatTypeId

[编辑 | 编辑源代码]

Global FloatTypeId:TTypeId=New TTypeId.Init( "Float",4 )

描述: 基本浮点型类型

DoubleTypeId

[编辑 | 编辑源代码]

Global DoubleTypeId:TTypeId=New TTypeId.Init( "Double",8 )

描述: 基本双精度型类型

StringTypeId

[编辑 | 编辑源代码]

Global StringTypeId:TTypeId=New TTypeId.Init( "String",4,bbRefStringClass() )

描述: 基本字符串类型

ObjectTypeId

[编辑 | 编辑源代码]

Global ObjectTypeId:TTypeId=New TTypeId.Init( "Object",4,bbRefObjectClass() )

描述: 基本对象类型

ArrayTypeId

[编辑 | 编辑源代码]

Global ArrayTypeId:TTypeId=New TTypeId.Init( "Null[]",4,bbRefArrayClass() )

描述: 基本数组类型

类型成员 - 字段或方法。

方法
  • 名称
  • TypeId
  • 元数据

TMember: 方法

[编辑 | 编辑源代码]
名称

Method Name$()

描述: 获取成员名称

TypeId

Method TypeId:TTypeId()

描述: 获取成员类型

元数据

Method MetaData$( key$="" )

描述: 获取成员元数据

类型字段

方法
  • 获取
  • GetInt
  • GetLong
  • GetFloat
  • GetDouble
  • GetString
  • 设置
  • SetInt
  • SetLong
  • SetFloat
  • SetDouble
  • SetString

TField: 方法

[编辑 | 编辑源代码]
获取

Method Get:Object( obj:Object )

描述: 获取字段值

GetInt

Method GetInt:Int( obj:Object )

描述: 获取整型字段值

GetLong

方法 GetLong:Long( obj:Object )

描述: 获取长整型字段值

GetFloat

方法 GetFloat:Float( obj:Object )

描述: 获取浮点型字段值

GetDouble

方法 GetDouble:Double( obj:Object )

描述: 获取双精度浮点型字段值

GetString

方法 GetString$( obj:Object )

描述: 获取字符串字段值

设置

方法 Set( obj:Object,value:Object )

描述: 设置字段值

SetInt

方法 SetInt( obj:Object,value:Int )

描述: 设置整型字段值

SetLong

方法 SetLong( obj:Object,value:Long )

描述: 设置长整型字段值

SetFloat

方法 SetFloat( obj:Object,value:Float )

描述: 设置浮点型字段值

SetDouble

方法 SetDouble( obj:Object,value:Double )

描述: 设置双精度浮点型字段值

SetString

方法 SetString( obj:Object,value$ )

描述: 设置字符串字段值

类型 方法

方法
  • ArgTypes
  • Invoke

TMethod: 方法

[编辑 | 编辑源代码]
ArgTypes

方法 ArgTypes:TTypeId[]()

描述: 获取方法参数类型

Invoke

方法 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

TTypeId: 方法

[编辑 | 编辑源代码]
名称

Method Name$()

描述: 获取类型的名称

元数据

Method MetaData$( key$="" )

描述: 获取类型元数据

SuperType

方法 SuperType:TTypeId()

描述: 获取父类型

ArrayType

方法 ArrayType:TTypeId(dims:Int = 1)

描述: 获取数组类型

ElementType

方法 ElementType:TTypeId()

描述: 获取元素类型

ExtendsType

方法 ExtendsType( typeId:TTypeId )

描述: 判断类型是否继承自某个类型

DerivedTypes

方法 DerivedTypes:TList()

描述: 获取派生类型列表

NewObject

方法 NewObject:Object()

描述: 创建一个新对象

Fields

方法 Fields:TList()

描述: 获取字段列表

信息: 仅返回该类型中声明的字段,不包括父类型中的字段。

方法

方法 Methods:TList()

描述: 获取方法列表

信息: 仅返回该类型中声明的方法,不包括父类型中的方法。

FindField

方法 FindField:TField( name$ )

描述: 按名称查找字段

信息: 在类型层次结构中搜索名为 name 的字段。

FindMethod

方法 FindMethod:TMethod( name$ )

描述: 按名称查找方法

信息: 在类型层次结构中搜索名为 name 的方法。

EnumFields

方法 EnumFields:TList( list:TList=Null )

描述: 枚举所有字段

信息: 返回类型层次结构中所有字段的列表

EnumMethods

方法 EnumMethods:TList( list:TList=Null )

描述: 枚举所有方法

信息: 返回类型层次结构中所有方法的列表 - TODO: 处理覆盖方法!

NewArray

方法 NewArray:Object( length, dims:Int[] = Null )

描述: 创建一个新数组

ArrayLength

方法 ArrayLength( array:Object, dim:Int = 0 )

描述: 获取数组长度

ArrayDimensions

方法 ArrayDimensions:Int( array:Object )

描述: 获取维度数量

GetArrayElement

方法 GetArrayElement:Object( array:Object,index )

描述: 获取数组元素

SetArrayElement

方法 SetArrayElement( array:Object,index,value:Object )

描述: 设置数组元素

TTypeId: 函数

[编辑 | 编辑源代码]
ForName

函数 ForName:TTypeId( name$ )

描述: 按名称获取类型

ForObject

函数 ForObject:TTypeId( obj:Object )

描述: 按对象获取类型

EnumTypes

函数 EnumTypes:TList()

描述: 获取所有类型的列表

华夏公益教科书