需求:
創(chuàng)建一個對象 , 使其繼承父類 : Named , Account , 成功調(diào)用父類方法
-- 在 table 'plist' 查找k
local function search( k , plist )
for i = 1 , #plist do
local v = plist[i][k] -- 嘗試第i個基類
if v then return v end
end
end
function createClass(...)
local c = {} -- 新類
local parents = {...}
-- 類可在其父類列表中的搜索方法
setmetatable( c , { __index = function(t, k )
return search( k , parents )
end
})
-- 將 'c'作為其實例的元表
c.__index = c
-- 為新類定義構(gòu)造函數(shù)(construction)
function c:new(o)
o = o or {}
setmetatable( o , c )
return o
end
return c -- 返回新建的類
end
-- 父類1 開始
Named = {}
function Named:getName()
return self.name
end
-- 父類1 結(jié)束
function Named:setName(n)
self.name = n
end
-- 父類2 開始
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
-- 父類2 結(jié)束
NamedAccount = createClass( Account , Named ) -- 創(chuàng)建新的 NamedAccount 類
account = NamedAccount:new( { name="Paul" } )
print("account:getName() : " .. account:getName())
print("account.balance : " .. account.balance)
注意 : 改進(jìn) 上面方法完成了多繼承 但效率不高,可如下修改,將父類的變量直接復(fù)制過來 , 但這樣缺點是, 運行后,不可進(jìn)行修改,因為并沒有真的繼承父類,只是簡單把父類的變量賦值過來而已
-- 修改上面代碼中的 setmetatable 方法
setmetatable( c , { __index = function(t, k )
local v = search( k , parents )
t[k] = v -- 保存下來, 以備下次訪問
return v
end
})