編譯者:sosei
Type
BlitzMax裏的Type類似於別的程序語言中的Class。類型是BlitzMax的一部分,使它成爲一種OOP(面向對象編程)語言。如果您剛接觸OOP,Type是最難處理的部分之一。
設置和創建Type
假設我們想要一艘宇宙飛船,那麼讓我們先爲它創建一個結構體:
Type SpaceShip 'declares a new type
Const help:String="this is what the structure contains"
Global fleet:String
Field max_speed:Float
Field armor:Int=2000
Field name:String
EndType 'ends declaration
Local ship:SpaceShip
這裏定義變量ship爲SpaceShip類型。這時的變量並不是個實例對象,要用下面方式創建一個實例對象:
ship = New SpaceShip
也可以合併定義:
Local ship:SpaceShip = New SpaceShip
注:變量裏其實放的是實例對象的地址。如果我們不創建一個新的ship,我們的ship將是= null。
現在可以使用ship.SpaceShipFieldName設置該對象的字段:
ship.max_speed = 3.5 'Read: Ship's MaxSpeed set to 3.5
Ship.armor = 5000 'Default was 2000 (See the type)
Ship.name = "wavebreaker"
繼續例子:
Local ship2:SpaceShip = New SpaceShip
ship.max_speed = 5.5
ship2 = ship
當給變量ship2賦值成ship中的地址,ship2原指向的實例對象地址就沒有被任何變量保存,那麼此實例對象將被BlitzMax自動刪除。一個實例對象可以有多個指向它的指針。實例對象本身是唯一的,但是它的地址可以駐留在幾個不同的變量中。
類型SpaceShip中的變量fleet是用關鍵字Global定義的,意味着這是類似於Python中的類變量。這種變量在其類型所派生的實例對象中是共享的。即使沒有該類型的任何實例,也可以使用它。類型中關鍵字Const聲明的也是所派生的實例對象中是共享的,跟Global的區別是這定義的是個常量。
例子:
Print SpaceShip.help
SpaceShip.fleet = "Quantum Light"
直接對類型SpaceShip的Global變量fleet賦值了。
TList類型
這是列表類型,列表比數組更具動態性,不用在聲明時就定下尺寸。
下面是一個用到列表的程序例子:
Global number_of_tanks = 10 'How many tanks to create?
' Having a Global like the one above makes it easy To change how the program
' acts at least in small examples like this. Now let's declare a new type
' called Tank.
Type TTank 'The extra T infront of the type name is good use
Field x#, y#
Field dir, armor = 100
Field speed# = 0.2, size = 25
EndType
Graphics 800,600
Global TankList:TList = CreateList() 'Create a list to store all tanks
' TankList:TList defines TankList To be of the List-Type, CreateList() returns
' a New List. The variable TankList will be used whenever you want To add
' remove or alter this TList.
' Note that TList is a BlitzMax built-in Type And it has it's own methods and
' functions.
' Create a bunch of new Tanks
For Local n = 1 To number_of_tanks ' number_of_tanks is a Global
Local NewTank:TTank 'Declares a variable to store our Tank-Type
'Put the address of this new Tank into variable NewTank
NewTank = New TTank
'Set a random armor 150 + 10,20,30,40 or 50
NewTank.armor = Rand( 5 )*10 + 150
'Random Start Location
NewTank.x = Rand( 5, 800 )
NewTank.y = Rand( 5, 600)
NewTank.dir = Rand( 0, 360 )
'Put this tank called NewTank into our TankList
ListAddLast( TankList, NewTank )
Next
While Not KeyDown(Key_Escape)
Cls
'Local T is declared to hold the current Tank each loop
'Because we called our Type TTank, Tank is availible as variable
For Local Tank:TTank = EachIn TankList
DrawOval( Tank.x, Tank.y, Tank.size, Tank.size )
DrawText "Number of Tanks : "+TankList.Count(), 20, 20
DrawText "Press ESC to exit", 20, 40 '20 is X-coordinate, 40 is Y
Tank.x:+ Tank.speed*Cos( Tank.dir )
Tank.y:+ Tank.speed*Sin( Tank.dir )
Next 'This loop will loop for every Tank that was added to TankList
Flip
Wend
Method
方法通常是類型的動作,它可以是FireShot()、Explode()、Turn()或Update()。
例子:
Type TWizard
Field x, y, mana
Method Teleport( x, y )
Self.x = x
Self.y = y
EndMethod
EndType
可以省略關鍵字Self,如下寫法:
Type TWizard
Field x, y, mana
Method Teleport( x2, y2 )
x = x2
y = y2
EndMethod
EndType
所以爲了可讀性,推薦不要省略關鍵字Self
注:有一個特殊的方法。方法New(),每次創建該類型的實例時都會運行該方法。
我們也可以寫成一個函數,但它看起來會是這樣的:
Type TWizard
Field x, y, mana
Function Teleport( Wizard:TWizard, x, y )
Wizard.x = x
Wizard.y = y
EndFunction
EndType
類型的方法和類型的函數之間的區別有兩點:
區別一,方法內可使用類型內的Global變量、常量、字段變量、方法、函數、類型,都可以直接引用。而類型的函數只可以直接使用類型內的Global變量、常量、函數、類型。
區別二,類型的方法只可以用類型派生的實例對象調用,類似Python中的實例方法;類型的函數既可以用類型派生的實例對象調用,也可以用類型直接調用,類似Python中的靜態方法。
例子:
Type TT
Const x_const:Int=666
Global y_var
Type SubTT
Field f
EndType
Function z_func()
Print "z_func"
EndFunction
Function test_func(y)
Print x_const
Local y_var:Int = y
Print y_var
Local s:SubTT
z_func()
EndFunction
EndType
Local object_var:TT = New TT
object_var.test_func(999)
TT.test_func(999)