面向对象(Object-Oriented)编程
Lua语言中的一张表就是一个对象,表与对象一样,可以拥有状态。
表与对象一样,拥有一个与其值无关的的标识(self)
两个具有相同值的对象(表)是两个不同的对象,而一个对象可以具有多个不同的值;
最后,表与对象一样,具有与创建者和被创建位置无关的生命周期。
参数self是所有面向对象语言的核心点。大多数面向对象语言都向程序员隐藏了这个机制。Lua语言同样可以使用冒号操作符隐藏该参数。
例:
Account = {
balance = 0,
withdraw = function (self, v)
self.balance = self.balance - v
end
}
function Account:deposit(v)
self.balance = self.balance + v
end
Account.deposit(Account, 200.00)
Account:withdraw(100.00)`
类(Class)
大多数面向对象语言提供了类的概念,类在对象的创建中扮演了模子的作用。
在这些语言中,每个对象都是某个特定类的实例。
Lua语言中没有类的概念,基于原型的语言中的一些做法来在Lua语言中模拟类。
每个对象可以有一个原型。原型也是一种普通的对象,当对象(类的实例)遇到一个未知操作时会首先在原型中查找。
功能快捷键
大多数面向对象语言提供了类的概念,类在对象的创建中扮演了模子的作用。 在这些语言中,每个对象都是某个特定类的实例。
Lua语言中没有类的概念,基于原型的语言中的一些做法来在Lua语言中模拟类。
每个对象可以有一个原型。原型也是一种普通的对象,当对象(类的实例)遇到一个未知操作时会首先在原型中查找。
在
l
u
a
中
调
用
方
法
一
定
要
用
冒
号
“
:
”
,
不
然
会
a
t
t
e
m
p
t
t
o
i
n
d
e
x
l
o
c
a
l
′
s
e
l
f
′
(
a
n
i
l
v
a
l
u
e
)
\color{#FF0000}{在lua中调用方法一定要用冒号“:”,不然会attempt to index local 'self' (a nil value)}
在lua中调用方法一定要用冒号“:”,不然会attempttoindexlocal′self′(anilvalue)
继承(Inheritance)
例:
Account = {balance = 0}
function Account:new( o )
o = o or {}
self.__index = self
setmetatable(o, 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。不过,现在执行new时,它的self参数指向的是SpecialAccount。
SpecialAccount = Account:new()
s = SpecialAccount:new{limit = 1000.00}
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:deposit(100)
s:withdraw(1800.00)
print(s.balance)
多重继承(Multiple Inheritance)
Lua语言中实现多重继承,关键在于把一个函数用作__index元方法,当一个表的元表中的__index字段为一个函数时,当Lua不能在原来的表中找到一个键时就会调用这个函数。
例:
require "Account"
-- 在表"plist"的列表中查找"k"
local function search(k, plist)
for i = 1, #plist do
-- 尝试第'i'个超类
local v = plist[i][k]
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
--为新类定义一个新的构造函数
function c:new( o )
o = o or {}
setmetatable(o, c)
return o
end
return c --返回新类
end
Named = {}
function Named:getname()
return self.name
end
function Named:setname(n)
self.name = n
end
NamedAccount = createClass(Account, Named)
acccount = NamedAccount:new{name = "Paul"}
print(acccount:getname())
var foo = 'bar';
私有性(Privacy)
Lua语言中标准的对象实现方式没有提供私有性机制,如果读者不想访问一个对象内的内容,那就不要去访问就是了。一种常见的做法是把所有私有名称的最后加上一个下画线,这样就能立刻区分出全局名称了。