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()
描述: 獲取所有型別的列表