我喜欢将 OOP 视为容器(对象)内的数据封装以及可以使用该数据完成的操作子集。还有很多内容,但我们假设这个简单的定义就是全部,并用它在 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)
作为表中键的字符串值的访问方式与 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()
很棒吧?我们现在可以将函数存储在表中,并且您可以再次看到它类似于其他 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
这样就可以用简单的方式解决它。也许与 Python 中的工作方式进行类比(方法总是有一个明确的自我)可以帮助您了解 Lua 中的工作方式。但是,在我们的方法调用中显式传递所有这些对象不是很不方便吗?是的,这也困扰着我,所以还有另一个捷径可以帮助你使用 OOP:
obj:hello() -- is the same as obj.hello(obj)
最后,我只是简单介绍了如何做到这一点。正如已指出的凯文·维米尔的评论 https://stackoverflow.com/questions/4799078/how-can-one-implement-oo-in-lua/4799895#comment13925487_4799078, the Lua 用户维基 http://lua-users.org/wiki/ObjectOrientedProgramming是有关该主题的极好的信息来源,您可以在那里了解如何实现本答案中忽略的 OOP 的另一个重要方面(私有成员、如何构造对象、继承等)。请记住,这种做事方式是 Lua 哲学的一小部分,它为您提供了能够构建更高级构造的简单正交工具。