在Lua中进行编程,对象

该行代码的目的是将实例对象的索引指向其所属的类,以便在实例对象中查找属性和方法时能够自动调用类中定义的属性和方法。它在每次创建对象时都被执行,以确保每个对象都有正确的索引。

原文链接 https://stackoverflow.com/questions/2761713

点赞
stackoverflow用户298661
stackoverflow用户298661

他们用于重定向表访问(local y = table[key]),这也在方法调用中使用。在上面那行中,对象o将会把访问键的任何尝试重定向到当前对象self,从而毫不费力地继承所有成员函数。也可能继承数据变量,这取决于__index是什么,以及它如何工作。

2010-05-03 22:52:59
stackoverflow用户1491
stackoverflow用户1491

Lua 不是面向对象的语言,但它具备编写面向对象代码的所有设施。然而,它是按照 JavaScript 风格的原型(prototyping)方式实现的。与显式创建类不同,先创建一个原型对象,然后克隆它以创建新实例。

当键不存在于表中时,__index 元方法被调用以在读取表中的值时执行键查找。因此,self.__index = self 本质上允许通过 o = o or {}setmetatable(o, self) 行创建的新“实例”继承 Account 类的所有方法和字段。

另请参阅:

2010-05-04 13:34:05
stackoverflow用户211771
stackoverflow用户211771

正如其他人所说的那样,self(即Account表)被用作分配给使用new创建的对象的元表。稍微简化一下(更多信息可在提供的链接中找到),当在'o'中找不到字段时,它会转到'Account'表,因为o的元表要求转到Account(这就是__index的作用)。

然而,它并不需要在每次创建对象时执行。你同样可以把它放在别处:

Account.__index = Account

这也能起到相同的作用。

稍微详细一点的解释是,如果一个对象o具有元表,并且元表具有设置__index字段,那么在o上执行的一个字段查找失败将使用__index来找到该字段(__index可以是表或函数)。如果o具有该字段,你不会去到它的元表的__index函数来获取信息。同样,我建议您在上面提供的链接中阅读更多。

2010-05-04 17:59:05
stackoverflow用户867990
stackoverflow用户867990

Lua文档在这一细节上有点含糊,这里的许多答案要么 echo Lua文档,要么没有彻底解释这个令人困惑的要点。

self._index = self 仅出现是为了新创建的对象 o 的好处;它对 Account 没有任何有意义或有功能性的影响。

_index 字段在元表上下文中才具有特殊含义;因此,self._index 对于 Account 只是一个普通的常规字段。然而,当 Account 用作 o 的元表时,_index 字段“变成”了 o 的元方法。因此,对于 Account 的字段是 o 的元方法。

当你将两个语句结合在一起...

(1)    setmetatable(o, self)
(2)    self._index = self

...你正在将 Account 用作第(1)行中的 o 的元表,并在第(2)行中将 o_index 元方法设置为 Account。在第(2)行中,您还将 Account 中的“普通旧字段”__index 设置为 Account。因此,self._index = self 的有用方面不是为 Account 设置 _index 字段,而是为 o 设置 _index 元方法。

下面的代码与上述代码功能相同:

    setmetatable(o, self)
    getmetatable(o)._index = self
2011-07-28 17:20:49
stackoverflow用户3074926
stackoverflow用户3074926

在 Lua 中创建对象(简单来说就是表格)与其他语言不太相同。基本思想是创建一个普通的表格,其中包含所有实例共有的属性(函数和值)。我将这个表格称为 CAT(即公共属性表格)。

如果在一个表格中引用一个属性,而 Lua 找不到该属性,有一种方法可以告诉 Lua 在哪里查找该属性。我们希望 Lua 在 CAT 中查找共同的属性。元表就是这样的答案。后面会详细介绍它的工作原理。

我们还需要在 CAT 中设置方法以便使用实例的值。Self 也是答案。当您这样调用一个表格函数(方法):tableName:methodName() 时,Lua 会自动将对表格对象的引用作为第一个参数。这个参数的名称是 self。尽管该方法位于 CAT 中,但 self 将引用特定的调用对象实例表。

假设我们有一个名为 Car 的 CAT。

metaCar = { __index = Car }
-- 这个表格将用作 Car 的所有实例的元表
-- Lua 会在实例中查找不到的属性在 Car 中查找

例如:

-- 实例表格称为 mustang
-- setmetatable(mustang, metaCar)

以下是一个通用函数,它创建新的实例对象并设置它的元表。如果 CAT 有一个构造函数(init),它也会执行。

function newObj(metatable)
..obj = {}      -- 创建新的空实例对象
..setmetatable(obj, metatable) –- 将元表连接到它上面
..if obj.init then  -- 如果 CAT 有一个 init 方法,执行它
....obj:init()
..end
..return obj
end
2013-12-06 17:45:33
stackoverflow用户1999185
stackoverflow用户1999185

请注意 setmetatable(o, self) 只是将 o 设置为 Account 的元表(默认为 nil)。这是原型绑定的第一步,但这还 不足以 使 oAccount 中搜索方法!

要使 o 搜索 Account 的方法,元表对象(Account)必须包含一个具有指向自身的值的 __index 事件,其中包含原型方法。

因此需要分两步完成:

  1. 创建具有 __index 事件的元表值
  2. 将元表设置为目标表。

如原书所述,这是“一个小优化”,通常您需要创建另一个模板表值作为 o 的元表。但在这种情况下,代码重用了 Account 表值,作为元表和原型对 象。

2020-09-25 12:44:37