1. 程式人生 > 其它 >十分鐘學會Lua五:類與繼承的實現

十分鐘學會Lua五:類與繼承的實現

Lua中沒有類,即沒有在物件生成中有模子的概念,但是有原型的概念。基於原型的語言(prototype-based language)中,每個物件可以有一個原型(prototype)。原型也是一種普通的物件,當物件(類的例項)遇到一個未知操作時會首先在原型中查詢。類和原型都是一種組織多個物件間共享行為的方式。

建立原型的方法如setmetatable(A, {__index = B}),即把B作為A的原型。下面的程式碼是簡單表達賬戶存取和提取的操作:

Account = { balance=0}

function Account : withdraw ( v)

self.balance = self.balance – v

end

function Account : deposit (v)

self.balance = self.balance + v

end

現在,需要實現類的概念,即Account作為類,下列程式碼中定義的a作為其物件。

local mt = {__index = Account}

function Account. new (o) --該函式用於新建賬戶,即建立物件

o = o or {f} --如果使用者沒有提供則建立一個新的表

setmetatable(o,mt ) --將mt作為新建立的物件的元表,而元表中的__index為Account類

return o

end

a = Account . new{ balance = 0}

a : deposit ( 100.00 ) --相當於 getmetatable(a).__index . deposit(a,100.00)

對於上述程式碼,我們可以進行一些改進。方法new會變成:

function Account : new ( o)

o = o or {}

self. __index = self

setmetatable(o, self)

return o

end

該改進是,不建立扮演元表角色的新表而是把表Account直接用作元表。第同時對new方法也使用冒號語法。加入了這兩個改動後,現在,當我們定義new ()函式時,隱藏的引數self得到的實參是Account,Account._index等於Account,並且 Account被用作新物件的元表。

若想從Account這個類派生一個子類SpecialAccount以允許客戶透支,那麼可以先建立一個從基類繼承了所有操作的空類:

SpecialAccount = Account :new()

直到現在,SpecialAccount還只是基於Account 類建立的一個物件例項。下面:

s = SpecialAccount : new{limit=1000.00}

SpecialAccount就像繼承其他方法一樣從 Account繼承了new,這是由於基於之前的改進,Account被用作新物件的元表。不過,現在執行new時,它的self引數指向的是SpecialAccount。因此,s 的元表會是 SpecialAccount,即s 繼承自SpecialAccount,而SpecialAccount又繼承自Account。

同時我們可以重新定義子類從基類繼承的任意方法,只需要編寫一個新方法即可,以修改SpecialAccount從Account類繼承的withdraw ()函式為例:

function SpecialAccount : withdraw (v)

if v - self.balance >= self.limit then

error "insufficient funds"

end

self.balance = self.balance – v

end

現在,當呼叫s:withdraw (200.00)時,因為Lua語言會在SpecialAccount中先找到新的withdraw方法,所以不會再從Account中查詢。