试图理解这个lua片段

时间:2012-03-08 11:01:50

标签: lua

我试图了解这个功能的作用。任何人都可以向我解释这个吗?

function newInstance (class)
    local o = {}
    setmetatable (o, class)
    class.__index = class
    return o
end

它被称为:

self = newInstance (self)

3 个答案:

答案 0 :(得分:6)

这个功能显然可以在Lua中提供一个OOP变体(在我看来有点草率)。

这是一个班级的工厂。

为清楚起见,可以重写如下:

C = { }

C.foo = function(self) -- just some method, so class would not be empty
  print("foo method called", tostring(self))
end

C.__index = C -- (A)

function newInstance(class)
  return setmetatable({ }, class) -- (B)
end

现在如果我们创建两个新的C实例,我们清楚地看到它们都有一个方法foo(),但是不同的自我:

o1 = newInstance(C)
o1:foo() --> foo method called  table: 0x7fb3ea408ce0

o2 = newInstance(C)
o2:foo() --> foo method called  table: 0x7fb3ea4072f0

foo方法是相同的:

print(o1.foo, o2.foo, o1.foo == o2.foo and "equal" or "different")
--> function: 0x7fb3ea410760    function: 0x7fb3ea410760    equal

这是因为表格C(“类”)是__index(A)以上)的o1o2的元表,在{{1}中设置}。但(B)o1实际上是两个不同的表,在o2处创建(“类实例”或“对象”)。

注意:我们在(B)C.__index设置为等于C,因此我们会重复使用一个表。以下具有相同的效果:

(A)

答案 1 :(得分:1)

这用于在Lua中实现面向对象的行为。 Lua使用基于原型的继承(类似于Javascript)而不是基于类的继承(如Java或C ++)。 我们的想法是所有类方法都作为原型对象的一部分实现,并且继承对象在调用时委托给原型。

例如,假设您希望类myClass提供方法getMagicNumber

local myClass = { 
     getMagicNumber = function(self) 
         return self.theNumber;
     end };

local obj = newInstance(myClass);
obj.theNumber = 42;
print(obj:getMagicNumber()); -- supposed to return 42

这是一个微不足道的例子,但我希望你明白这个想法。会发生什么:newInstance创建一个新表,其metatable指向myClass,并确保metatable的__index字段也指向myClass。 正如__index上的Lua手册所描述的,当您现在尝试在该新表上调用getMagicNumber时,会发生以下情况:首先Lua尝试在getMagicNumber表中找到字段obj。由于该表为空,它现在在其__index表(myClass)中搜索该字段。由于该字段在那里找到,它现在调用myClass中的函数。

Programming in Lua如果您需要了解更多信息,请详细讨论此机制。

答案 2 :(得分:1)

你并不孤单我花了很多时间来修改这段代码。这是我的解释

每个表都可以有一个netatable,metatable可以存储其他通过名称索引的函数,而setmetatable自然地设置了metatable的值。

行class._index = ..是神奇发生的地方。

当你尝试使用self.fn1()调用函数时,然后lua在自己中查找名称fn1。如果它找不到它,那么它会查找表__index的self's metatable,并在那里存储的表中查找'fn1'。

现在你的示例中的self的metatable是class,所以lua在metatable(类)中查找一个__index条目,看看该表中是否有一个名为fn1的函数,并且有,所以它被返回。你需要将类的__index设置回自身,这样lua才能看到同样的元数据 - 令人困惑嘿。

(另外,对__index的赋值只需要发生一次,但出于某种原因,它总是在所有lua示例中的new运算符中完成 - 我将它放在我的类中的new之外 - 节省几个周期)

然后返回新表o,lua被垃圾收集,因此返回本地每次都会创建一个新表。

function newInstance (class)
    local o = {}
    setmetatable (o, class)
    class.__index = class
    return o
end

HTH