Lua的表在某种意义上也可以看做对象,表有状态(成员变量),可以有自己的成员函数。
一.“类”与“对象(instance)”的实现
为了使对象有独立的生命周期,故在定义方法的时候带上一个额外的参数,来表示方法的作用对象,在Lua中这个对象就是self.使用self参数定义函数后,这个函数就可以作用在多个对象上。
1.1 . 和 :的区别:
①使用.访问的方法,声明时需要带上一个额外的参数,表示方法作用的对象,这个参数为self,调用时参数列表要显式说明当前调用这个方法的对象
②使用:访问的方法,声明时可以隐藏self的参数声明,即冒号的效果相当于在函数定义和调用的时候
1.2示例代码
Account = {
balance = 0,
withdraw = function(self, v)
self.balance = self.balance - v
print(self.balance)
end
}
function Account:deposit(v)
self.balance = self.balance + v
print(self.balance)
end
--使用.参数列表要显式声明所属的对象
Account.deposit(Account,200.00)
--使用冒号则可以参数列表可以不传当前调用的对象
Account:withdraw(50.00)
a1 = Account;
Account = nil;
a1.withdraw(a1,100.0);
二.类的实现
Lua不存在类的概念,但是Lua是基于prototyoe的预言,所以在Lua中可以模仿类的概念。每个对象都有一个prototype,可以把这里对象拥有的prototype当做这个对象的父类,在Lua中prototype的设置可以通过给对象设置元表。而这个元表拥有__index元方法以及__newindex元方法,分别用于查找(对象调用它自己不存在的成员变量时会到它的prototype中查找) 更新.
a = Account : new{balance = 0}
a:deposit(666.00)--当在表a找不到deposit方法时,去Account中找
三.继承的实现
即可以让类访问其他类的方法。
--基类Account
Account = {balance = 0}
function Account:new(o)
o = o or {}
setmetatable(o,self)
o.__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.banlance - v
end
--~ --从基类Account派生出一个子类SpecialAccount
--~ --增添功能:这个子类允许客户取款超过它的存款余额限制
SpecialAccount = Account:new()
s = SpecialAccount:new{limit = 1000.00} --当new方法执行时self参数指向SpecialAccount
--SpecialAccount的特殊之处在于可以重定义从类中继承来的方法
function SpecialAccount:withdraw(v)
if v-self.balance >= self:getLimit() then
error "insufficient funds"
end
self.balance = self.balance - v
end
function SpeicialAccount:getLimit()
return self.limit or 0
end
四.多重继承:一个类有多个父类
实现的关键:将函数用作__index。当一个表的metatable存在一个__index函数时,如果Lua调用的一个原始表中不存在的函数时,它会调用这个__index指定的函数,这样就可以用__index实现在多个父类中查找子类不存在的域.
4.1可以定义一个函数createClass来完成创建子类的功能,而通过给这个方法中定义的子类对象设置__index,而这个__index是一个函数,到search方法中去多个父类中查找子类对象中不存在的域.
--k为键 而plist是父类的集合
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 = {} --新的子类
--通过设置元表 可以遍历查找父类中的每个方法
setmetatable(c,{__index = function(t,k)
return search(k.arg)
end
})
c.__index = c
--定义一个新的构造函数
function c:new(o)
o = o or {}
setmetatable(o,c)
return o
end
return c
end
五.私有性
Lua的元机制(meta-mechanisms)可以实现很多不同的机制。状态可以被保存在方法的闭包内。
函数创建一个表来描述对象的内部状态,并保存在局部变量self(故方法只能用.访问)中->函数为对象的每一个方法创建一个闭包(嵌套的函数实例)->函数创建并返回外部对象,而外部对象将局部方法指向最终要实现的方法。
--Single-Method的对象实现方法 实际上是一个基于重要的参数而执行不同的任务的分派的方法
function newObject(value)
return function(action,v)
if action == "get" then return value
elseif action == "set" then value = v
else error("invalid action")
end
end
end
--测试
d = newObject(0)
print(d("get"))
d("set",10)
print(d("get"))