在lua中编程,对象

时间:2010-05-03 22:47:19

标签: lua

示例代码:

function Account:new (o)
  o = o or {}   -- create object if user does not provide one
  setmetatable(o, self)
  self.__index = self
  return o
end

取自:

http://www.lua.org/pil/16.1.html

目的是什么:

self.__index = self

行?为什么每次创建对象时都会执行它?

6 个答案:

答案 0 :(得分:5)

正如其他人所说,selfAccount表)用作分配给使用new创建的对象的元表。当在“o”中找不到字段时,稍微简化(在提供的链接上提供更多信息),它会转到“帐户”表,因为o的metatable表示转到帐户(这是__index所做的)。

但是,每次创建对象时都不需要执行它。你可以很容易地把它粘在某个地方:

Account.__index = Account

它也可以。

更长的故事是,如果对象o具有元表,并且该元表具有__index字段集,则{{1> 字段查找{{1}将使用o来查找字段(__index可以是表或函数)。如果__index设置了字段,则不会转到其metatable的o函数来获取信息。不过,我再次鼓励您阅读上面提供的链接。

答案 1 :(得分:4)

Lua文档在这个细节上有点模糊,这里的许多答案要么回应Lua文档,要么没有彻底解释这个令人困惑的小问题。

self._index = self纯粹是为了新创建的对象o的利益而存在;它对Account没有任何意义或功能影响。

_index字段在元表的上下文中只有特殊含义;因此self._index只是Account的普通旧常规字段。但是,当Account用作o的元表时,_index字段“变为”o的元方法。 (那么Account的字段是o的元方法。)

当您将这两个陈述合并时......

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

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

以下功能相同:

    setmetatable(o, self)
    getmetatable(o)._index = self

答案 2 :(得分:3)

Lua不是面向对象的语言,但它具有编写面向对象代码的所有功能。但是,它以prototyping方式和JavaScript完成。不是显式创建类,而是创建原型对象,然后克隆以创建新实例。

当表中的密钥尚未存在时,将调用__index元方法对表的读访问执行密钥查找。因此,self.__index = self基本上允许通过Accounto = o or {}行中创建的新“实例”继承setmetatable(o, self)“类”的所有方法和字段。

另见:

答案 3 :(得分:0)

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

答案 4 :(得分:0)

创建对象(简称为Tables)与Lua完全不同。 基本思想是创建一个包含所有实例共有的属性(函数和值)的常规表。这个表,我将称为公共属性表的CAT。

如果你在表中引用一个属性而Lua找不到这个属性,那么就有办法告诉Lua在哪里寻找属性。我们希望Lua在CAT中查找常用属性。 Metatables回答了这个需求。更多关于以后的工作方式。

我们还需要CAT中的方法才能使用实例值。 自我需要的答案。当您以这种方式调用表函数(方法):tableName:methodName()时,Lua会自动将对象的引用作为第一个参数。此参数的名称为self。即使该方法位于CAT中,self也将引用特定的调用对象实例表。

假设我们有一个叫做Car的CAT。

metaCar = { __index = Car }  
-- this table will be used as the metatable for all instances of Car  
-- Lua will look in Car for attributes it can't find in the instance

例如:

-- instance table is called mustang    
-- setmetatable(mustang, metaCar)

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

function newObj(metatable)  
..obj = {}      -- create new empty instance object  
..setmetatable(obj, metatable) –- connect the metatable to it  
..if obj.init then  -- if the CAT has an init method, execute it  
....obj:init()  
..end  
..return obj  
end

答案 5 :(得分:0)

请注意,setmetatable(o, self)仅将Account设置为o的元表(否则默认为 nil )。这是原型绑定的第一步,但还不足以使Account功能可以从o进行搜索!

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

所以必须分两个步骤完成

  1. 通过__index事件创建一个元表值
  2. 可设置为目标表。

如原始书籍中所述,这是“一个小的优化”-您通常需要创建另一个模具表值作为o的元表。但是在这种情况下,代码重新使用了Acccount表值,将其作为元表和原型对象。