Lua 中只存在表(Table)这么唯一一种数据结构,但依旧可以玩出面向对象的概念。
添加成员函数
struct
里可以添加函数是从C 过渡到 C++ 的第一认识的话,为 Table 添加函数也可以算是认识 Lua 是如何面向对象的第一步吧。
player = { health = 200 } --> 一个普通的 player 表,这里看作是一个对象
function takeDamage(self, amount)
self.health = self.health - amount
end
takeDamage(player, 20) --> 调用
takeDamage
塞进 player
中咧?答案是直接定义进去:
player = { health = 200 }
function player.takeDamage(self, amount)
self.health = self.health - amount
end
player.takeDamage(player, 20) --> 调用
player
表中添加了一个叫做 takeDamage
的字段,和下面的代码是一样的:
player = {
health = 200,
takeDamage = function(self, amount) --> Lua 中的函数是 first-class value
self.health = self.health - amount
end
}
player.takeDamage(player, 20) --> 调用
player.takeDamage(player,20)
稍显不和谐(据说用术语叫做 DRY),于是就要出动「冒号操作符」这个专门为此而生的语法糖了:
player:takeDamage(20) --> 等同于 player.takeDamage(player, 20)
function player:takeDamage(amount) --> 等同于 function player.takeDamage(self, amount)
从对象升华到类
prototype
实现面向对象,Lua则通过 Metatable 实现与 prototype
类似的功能。
Player = {}
function Player:create(o) --> 参数 o 可以暂时不管
o = o or { health = 200 } --> Lua 的 or 与一般的 || 不同,如果非 nil 则返回该非 nil 值
setmetatable(o, self)
self.__index = self
return o
end
function Player:takeDamage(amount)
self.health = self.health - amount
end
playerA = Player:create() --> 参数 o 为 nil
playerB = Player:create()
playerA:takeDamage(20)
playerB:takeDamage(40)
__index
域设置了「如何进行索引」的方法。例如调用foo.bar
时,如果在 foo
中没有找到名为 bar
的域时,则会调用Metatable:__index(foo,bar)
。于是:
playerA:takeDamage(20)
playerA
中并不存在 takeDamge
函数,于是求助于Metatable:
getmetatable(playerA).__index.takeDamage(playerA, 20)
带入 Metatable 后:
Player.__index.takeDamage(playerA, 20)
Player
的 __index
在 create
时被指定为 self
,所以最终变为:
Player.takeDamage(playerA, 20)
takeDamage
的 self
得到了正确的对象 playerA
。
继承
o
么?
RMBPlayer = Player:create()
function RMBPlayer:broadcast(message) --> 为子类添加新的方法
print(message)
end
function RMBPlayer:takeDamage(amount) --> 子类重载父类方法
self.health = self.health - amount / (self.money / 100)
end
vip = RMBPlayer:create { money = 200 } --> 子类添加新成员(单个 Table 作为参数可以省略括号)
vip:takeDamage(20)
vip:broadcast("F*ck")
以上便是 Lua 中实现面向对象的基本方法。