第一版是針對 Lua 5.0 所寫的。雖然在後續版本中仍然有很大的關聯性,但仍有一些差異。
第四版針對 Lua 5.3,可在 Amazon 和其他書店購買。
購買這本書,您也同時協助 支援 Lua 專案。
![]() |
Lua 程式設計 | ![]() |
第二部。表格和物件 第 16 章。物件導向程式設計 |
由於類別是物件,因此它們也可以從其他類別取得方法。這使得在 Lua 中實作繼承(以通常的物件導向意義)變得相當容易。
假設我們有一個基礎類別,例如 Account
Account = {balance = 0} function Account:new (o) o = o or {} setmetatable(o, self) self.__index = self return o end function Account:deposit (v) self.balance = self.balance + v end function Account:withdraw (v) if v > self.balance then error"insufficient funds" end self.balance = self.balance - v end
從該類別,我們要衍生一個子類別 SpecialAccount
,允許客戶提領超過其餘額的金額。我們從一個空類別開始,它僅從其基礎類別繼承所有操作
SpecialAccount = Account:new()到目前為止,
SpecialAccount
僅是 Account
的一個執行個體。現在發生了美好的事情
s = SpecialAccount:new{limit=1000.00}
SpecialAccount
從 Account
繼承 new
,就像任何其他方法一樣。然而,這次當 new
執行時,self
參數將參考 SpecialAccount
。因此,s
的元表將會是 SpecialAccount
,其在索引 __index
的值也是 SpecialAccount
。因此,s
從 SpecialAccount
繼承,而 SpecialAccount
從 Account
繼承。當我們評估
s:deposit(100.00)Lua 無法在
s
中找到 deposit
欄位,因此它會尋找 SpecialAccount
;它也無法在其中找到 deposit
欄位,因此它會尋找 Account
,並在那裡找到存款的原始實作。
讓 SpecialAccount
變得特別的是,它可以重新定義從其超類別繼承的任何方法。我們所要做的就是撰寫新的方法
function SpecialAccount:withdraw (v) if v - self.balance >= self:getLimit() then error"insufficient funds" end self.balance = self.balance - v end function SpecialAccount:getLimit () return self.limit or 0 end現在,當我們呼叫
s:withdraw(200.00)
時,Lua 沒有轉到 Account
,因為它首先在 SpecialAccount
中找到了新的 withdraw
方法。由於 s.limit
是 1000.00(請記住,我們在建立 s
時設定了這個欄位),所以程式執行了提款,讓 s
變成負餘額。
Lua 中物件導向的一個有趣面向是,您不需要建立一個新類別來指定一個新的行為。如果只有一個物件需要一個特定的行為,您可以直接在物件中實作它。例如,如果帳戶 s
代表某個特殊客戶,她的額度總是餘額的 10%,您可以只修改這個單一帳戶
function s:getLimit () return self.balance * 0.10 end在那個宣告之後,呼叫
s:withdraw(200.00)
執行了 SpecialAccount
中的 withdraw
方法,但是當那個方法呼叫 self:getLimit
時,它呼叫的是這個最後的定義。
版權所有 © 2003–2004 Roberto Ierusalimschy。保留所有權利。 | ![]() |