Lua中的类,它是如何工作的?

我是 Lua 的新手,我正在尝试了解它的面向对象部分,例如:

lkw = {}
lkw.la= 0

function lkw:func(ge)
    self.la = self.la + ge
end

function lkw:new()
    local res = {}
    setmetatable(res, self)
    self.__index = self
    return res
end

mylkw = lkw:new()

在这个例子中,“类” lkw 可以使用 new 来创建对象,但是 self 和 index 是什么意思? 应该将 self 视为 Java/C++ 中的 this,而 index 是什么?

点赞
用户204011
用户204011

这种面向对象编程风格在 Lua 中很常见。我不喜欢它,因为对我来说不够明确,但让我试着解释一下。

有两个令人困惑的事情:函数定义中使用 : 糖语法和使用“类”作为其实例的元表。

首先,function a:b(...) 相当于 a.b = function(self, ...),因此让我们去掉所有糖:

lkw = {}
lkw.la = 0

lkw.func = function(self, ge)
    self.la = self.la + ge
end

lkw.new = function(self)
    local res = {}
    setmetatable(res, self)
    self.__index = self
    return res
end

mylkw = lkw.new(lkw)

现在,这是“原型继承”。lkw 是像 mylkw 这样实例的“原型”。这与“类”类似但有所不同。

当调用 new 构造函数时,将 lkw 作为 self 参数传递。

构造函数的第二和第三行很奇怪。这可能更容易理解:

lkw.new = function(self)
    local res = {}
    setmetatable(res, {__index = lkw})
    return res
end

即:如果我们在实例中找不到某些东西,我们会去寻找原型中的内容。

这就解释了 func 如何工作。第一次调用它时,实例将不包含 la 键,因此会使用 lkw.la

代码不是以这种方式编写的原因是这种奇特的构造方式允许“原型继承”:您可以在 mylkw 上调用“new”并获得“实例的实例”(即在原型继承中,实例和子类是同一个东西)。

我认为这是一个非常令人困惑的特性。作为参考,以下是我将会编写的执行基本相同的功能但没有继承的代码:

local methods = {
    func = function(self, ge)
        self.la = self.la + ge
    end
}

local lkw = {
    new = function()
        return setmetatable({la = 0}, {__index = methods})
    end
}

local mylkw = lkw.new()
2014-11-26 23:33:13