面向对象有三个要点:
1. 对象拥有状态;
2. 对象拥有独立的标志;
3. 对象有独立的生命周期。
在Lua语言中,使用self参数表示对象的独立标志。
在完成上面三个要点后,仍需要解决类,继承,私密性的问题。
Lua中没有类的概念,但是有原型,作为对象间共享行为的方式。如果需要设定原型,只需要用以下语句:
-- 使用b作为a的原型
setmetable(a, {__index = b})
当Lua无法在a中找到某个条目时,会进一步去找元表的__index条目。也就是,会发生以下的调用:
getmetable(a).__index.方法名()
Lua相当于调用了原型中的函数,但是传入了不一样的self参数。
当需要实现继承的时候,我们可以先从父类继承,然后重写子类的函数,因为Lua会首先寻找子类中的实现,找不到的时候才会去父类中查找。
我们可以使用一个函数作为__index实现多重继承,如下:
local function search(k, plist)
for i = 1, #plist do
local v = plist[i][k]
if v then return v end
end
end
function createClass(...)
local c = {}
local parent = {...}
--注意区分下列三种
function c (self, o)
o = o or {}
setmetatable(o, c)
return o
end
c.__index = c
setmetatable(c, { __index = function (t, k)
return search(k, parents)
end})
return c
end
由于搜索有一定的复杂性,导致性能下降。可以将搜索得到的方法复制到子类中,如下:
local function search(name, plist)
for i = 1, #plist do
local func = plist[i][name]
if func then
t[name] = func
return func
end
end
end
优点是,访问继承的方法跟访问局部方法一样快。缺点是系统运行后无法即时修改方法。
Lua并没有设计私密性机制,一般可以通过两个table表示一个对象,一个table保存对象的状态,另一个用于对象操作,即接口。注意此时访问接口时可以不用传入self参数。当对象只有一个方法时,可以直接将方法返回,无需创建接口table。
网友评论