【问题标题】:Difference between table in __index field and metatable__index 字段中的表与元表的区别
【发布时间】:2017-10-14 21:09:19
【问题描述】:

我正在使用 Lua 学习面向对象的编程。我无法理解在实例的 __index 字段中分配表和为实例设置元表之间的功能差异。我查看了官方 Lua 的参考手册,但我没有完全掌握其中的区别。例如,要创建 Account 类的实例,它将 Account 类(self)的 __index 字段设置为自身,然后将实例的元表设置为 Account 类。

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

这里发生了什么?在这种情况下,为什么 Account 将它自己的索引设置为自己?如果实例 'o' 只是使用 Account 类作为其元表,那么在这种情况下,真正的元表有什么用?为什么 Lua 允许类成为其实例的元表?

据我了解,元表应该是仅由元方法(__newindex、__index、__add 等)组成的表。但是该示例将 __index 作为 Account 类的字段,此时,它不是元表,也没有分配给它的元表,因此如果有意义的话,分配会查找另一个元表。

提前致谢。

【问题讨论】:

    标签: lua


    【解决方案1】:

    在示例中,Account 是元表,o 是实例。由于Account 被用作一个类,它需要一个__index 字段来定义常规方法。 __index 字段是在构造函数中定义的,因为调用构造函数的行为意味着 Account 被用作一个类。

    由于在构造函数中定义__index有点多余,你会经常看到这样的例子:

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

    我无法理解在实例的 __index 字段中分配表和为实例设置元表之间的功能差异。

    您通常不会将__index 放在一个实例中。 (尽管在 PiL 示例中,任何对象都可能被用作另一个类。请谨慎使用。)为实例设置元表是将元方法应用于该实例。

    据我了解,元表应该是仅由元方法(__newindex、__index、__add 等)组成的表。

    元表可以包含的内容没有限制,但是表需要定义至少一个元方法才能在用作元表时产生任何效果。

    元方法本质上提供运算符重载。这意味着元表可以定义其他表的行为。 __index 是 OOP 真正重要的元方法,因为这就是我们可以使用实例访问类中定义的方法和变量的方式。

    为什么元表的__index 通常指向它自己?因为否则,我们将需要另一个表来保存常规方法。对于简单的 OOP 框架,让一张表完成两项工作会更容易。

    简答:元表定义实例的元方法。 __index 是将字段访问路由到另一个表的元方法(如果 __index 是一个表。它也可以是一个函数)。

    【讨论】:

    • 感谢您的快速答复。关于分配“Account.__index = Account”,我是否正确地说这仅在我希望用户创建帐户实例时才需要,否则不需要分配?
    • 是的。我不知道有任何其他理由这样做。
    • 好的,谢谢!这有很大帮助。我现在终于明白了。我来自 C++/Java/C# 背景,因此 Lua 版本的面向对象设计需要对我的思维方式进行一些调整。
    • 乐于助人。不要忘记将答案标记为已接受。 (请参阅向上/向下投票箭头下方的复选标记。)
    猜你喜欢
    • 2023-03-17
    • 2017-02-01
    • 2018-10-25
    • 1970-01-01
    • 2021-12-19
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多