LUA学习笔记 -- 类

2020-06-21  本文已影响0人  奥利奥蘸墨水

引述

LUA中的表就是一个对象:

对象有自己的操作,表也有,例:

People = {money = 0}

function People.earn_money(money)
    People.money = People.money + money
end

上面的代码创建了一个新函数,并将该函数存入People的earn_money字段,然后就可以进行如下调用:

People.earn_money(100)

接下来换一种方法表示这个函数:

function People.earn_money(self, money)
    self.money = self.money + money
end

上述方法通过对操作的接受者进行操作,替代了原来的直接调用全局名称People

通过使用参数self,可以对多个对象调用相同的方法:

People = {money = 0}

function People.earn_money(self, money)
    self.money = self.money + money
end

p1 = {money = 0, earn_money = People.earn_money}
p2 = {money = 0, earn_money = People.earn_money}

p1.earn_money(p1, 100)
p2.earn_money(p2, 200)

print(p1.money) -- 100
print(p2.money) -- 200

LUA中有一种语法糖,使用冒号操作符隐藏传入的self参数,我们可以将上述函数重写为:

function People:earn_money(money)
    self.money = self.money + money
end

可以使用冒号来定义函数,同样也可以使用冒号来调用方法,所以可以将上述例子重写为:

People = {money = 0}

function People:earn_money(money)
    self.money = self.money + money
end

p1 = {money = 0, earn_money = People.earn_money}
p2 = {money = 0, earn_money = People.earn_money}

p1:earn_money(100)
p2:earn_money(200)

print(p1.money) -- 100
print(p2.money) -- 200

类(Class)

LUA语言中本没有类的概念,虽然元表的概念在某种程度上与类的概念相似,但是把原表当作类使用在后续会比较麻烦。相反,我们可以参考基于原型的语言中的一些做法来在LUA语言中模拟类。在这些语言中,对象不属于类,每个对象可以有一个原型。原型也是一种普通的对象,当对象遇到遇到一个未知操作时,会首先在原型中查找。要在这种语言中表示一个类,我们只需要创建一个专门被用作其他对象(类的实例)的原型对象即可。类和原型都是一种组织多个对象间共享行为的方式。

在LUA语言中,如果有两个对象A和B,要让B成为A的一个原型,只需要:

setmetatable(A, {__index = B})

使用上述的People的例子,我们可以使用__index方法让这些新对象从People中继承earn_money操作:

People = {money = 0}

function People:earn_money(money)
    self.money = self.money + money
end

function People.new(o)
    o = o or {}
    setmetatable(o, {__index = People})
    return o
end

p1 = People.new{money = 0} -- 创建p1对象

p1:earn_money(100) -- getmetatable(p1).__index.earn_money(p1, 100)

print(p1.money) -- 100

在上述例子中,我们让p1的元表设置为{__index = People},这样当p1对象中找不到earn_money方法时,就会去元表中的__index中搜索,此时实际上发生了如下调用:

getmetatable(p1).__index.earn_money(p1, 100)

再使用LUA提供的语法糖(冒号方法),可以将上述new函数写成如下:

function People:new(o)
    o = o or {}
    self.__index = self
    setmetatable(o, self)
    return o
end

继续上面的例子,p1调用earn_money方法的时候会按照如下格式调用:

p1:earn_money(100)

实质上调用方式是:

p1.earn_money(p1, 100)

那么就是执行了:

p1.money = p1.money + 100

等号后面p1.money是继承父类的0,赋值完成之后,p1就拥有了money这个属性,并且值为100,此后再调用此属性的时候就不会再涉及元方法了。

上一篇 下一篇

猜你喜欢

热点阅读