lfz*_*cki 35
我喜欢将OOP视为容器(Object)中的数据封装,以及可以使用此数据完成的操作子集.还有更多内容,但让我们假设这个简单的定义是全部并在Lua中构建一些东西(对其他OO实现的熟悉也可以为读者带来很好的推动).
任何对Lua有一点了解的人都知道,表是存储键值对的一种巧妙方式,并且与字符串结合,事情开始变得非常有趣:
local obj = {} -- a new table
obj["name"] = "John"
obj["age"] = 20
-- but there's a shortcut!
print("A person: " .. obj.name .. " of the age " .. obj.age)
Run Code Online (Sandbox Code Playgroud)
字符串值作为表中的键可以以与C语言中的结构成员非常相似的方式访问,或者以C++/Java和类似语言中的对象的公共成员访问.
现在有一个很酷的魔术:让我们将它与匿名函数结合起来.
-- assume the obj from last example
obj.hello = function ()
print("Hello!")
end
obj.goodbye = function ()
print("I must be going.")
end
obj.hello()
obj.goodbye()
Run Code Online (Sandbox Code Playgroud)
真棒吗?我们现在有了将函数存储在表中的方法,并且您再次可以看到它类似于在其他OOP语言中使用方法的方式.但缺少一些东西.我们如何在方法定义中访问属于我们对象的数据?通常通过将表中函数的签名更改为以下内容来解决此问题:
-- assume the obj from last example
obj.inspect = function (self)
print("A person: " .. self.name .. " of the age " .. self.age)
end
obj.hello = function (self)
print(self.name .. ": Hello! I'm " .. self.name)
end
obj.goodbye = function (self)
print(self.name .. ": I must be going.")
end
-- now it receives the calling object as the first parameter
obj.inspect(obj) -- A person: John of age 20
obj.hello(obj) -- John: Hello! I'm John
obj.goodbye(obj) -- John: I must be going
Run Code Online (Sandbox Code Playgroud)
这以一种简单的方式解决了这个问题.也许平行于Python中的工作方式(方法总是得到一个明确的自我)可以帮助你学习如何在Lua中工作.但是男孩,在我们的方法调用中明确地传递所有这些对象不是很不方便吗?是的,它也困扰我,所以还有另一个快捷方式来帮助你使用OOP:
obj:hello() -- is the same as obj.hello(obj)
Run Code Online (Sandbox Code Playgroud)
最后,我刚刚谈到了如何做到这一点.正如Kevin Vermeer的评论所指出的那样,Lua Users Wiki是关于这个主题的极好的信息来源,在那里你可以学到如何实现在这个答案中被忽略的OOP的另一个重要方面(私人成员,如何构造对象,继承,...).请记住,这种做事方式是Lua哲学的一小部分,为您提供简单的正交工具,能够构建更高级的构造.
Nic*_*unt 11
对于快速而肮脏的oo实现,我做了类似的事情 -
function newRGB(r,g,b)
return {
red=r;
green=g;
blue=b;
name='';
setName = function(self,name)
self.name=name;
end;
getName = function(self)
return self.name;
end;
tostring = function(self)
return self.name..' = {'..self.red..','..self.green..','..self.blue..'}'
end
}
end
Run Code Online (Sandbox Code Playgroud)
然后可以使用像 -
blue = newRGB(0,0,255);
blue:setName('blue');
yellow = newRGB(255,255,0);
yellow:setName('yellow');
print(yellow:tostring());
print(blue:tostring());
Run Code Online (Sandbox Code Playgroud)
对于更全功能的方法,我会使用eemrevnivek提到的oo库.你也可以在这里找到一个简单的类函数,它介于完全在库和快速和脏之间.
这已经回答了,但无论如何,这是我的oop实现:middleclass.
lib提供了创建类,实例,继承,多态和(原始)mixin的最低限度,具有可接受的性能.
样品:
local class = require 'middleclass'
local Person = class('Person')
function Person:initialize(name)
self.name = name
end
function Person:speak()
print('Hi, I am ' .. self.name ..'.')
end
local AgedPerson = class('AgedPerson', Person) -- or Person:subclass('AgedPerson')
AgedPerson.static.ADULT_AGE = 18 --this is a class variable
function AgedPerson:initialize(name, age)
Person.initialize(self, name) -- this calls the parent's constructor (Person.initialize) on self
self.age = age
end
function AgedPerson:speak()
Person.speak(self) -- prints "Hi, I am xx."
if(self.age < AgedPerson.ADULT_AGE) then --accessing a class variable from an instance method
print('I am underaged.')
else
print('I am an adult.')
end
end
local p1 = AgedPerson:new('Billy the Kid', 13) -- this is equivalent to AgedPerson('Billy the Kid', 13) - the :new part is implicit
local p2 = AgedPerson:new('Luke Skywalker', 21)
p1:speak()
p2:speak()
Run Code Online (Sandbox Code Playgroud)
输出:
Hi, I am Billy the Kid.
I am underaged.
Hi, I am Luke Skywalker.
I am an adult.
Run Code Online (Sandbox Code Playgroud)