如何在 Lua 中实现类和实例化?

这个问题起源于http://tylerneylon.com/a/learn-lua/。教程包括代码:

Dog = {dog1 = '原始狗类'}
function Dog.new(self, ... )
    newObj = {sound = '汪汪'}
    self.__index = self
    return setmetatable(newObj, self)
end

function Dog.makeSound(self, ... )
    print('我说' .. self.sound)
end

print('Dog=', Dog)
print('Dog元表=', getmetatable(Dog))  -- 这将不会输出任何东西

myDog = Dog.new(Dog)
print('\nmyDog=', myDog)
print('myDog元表=', getmetatable(myDog))
myDog.makeSound(myDog)

这是教程中上述代码的结果:

wirelessprvnat-172-17-106-141:Programming frankhe$ th test2.lua
Dog=  {
  makeSound : function: 0x0a6cec20
  dog1 : "原始狗类"
  new : function: 0x0a6cec00
}
Dog元表=  nil

myDog=  {
  sound : "汪汪"
}
myDog元表=  {
  makeSound : function: 0x0a6cec20
  __index :
    {
      makeSound : function: 0x0a6cec20
      __index :
        {
          makeSound : function: 0x0a6cec20
          __index :
            {
              makeSound : function: 0x0a6cec20
              __index :
                {
                  makeSound : function: 0x0a6cec20
                  __index : {...}
                  dog1 : "原始狗类"
                  new : function: 0x0a6cec00
                }
              dog1 : "原始狗类"
              new : function: 0x0a6cec00
            }
          dog1 : "原始狗类"
          new : function: 0x0a6cec00
        }
      dog1 : "原始狗类"
      new : function: 0x0a6cec00
    }
  dog1 : "原始狗类"
  new : function: 0x0a6cec00
}
我说汪汪

附加一张照片更清晰地描述这个问题

虽然教程中的代码成功地打印了 '我说汪汪',但是myDog的元表显然不是我们期望的。因此,我的解决方案如下(Dog.new中的区别):

function Dog.new(self, ... )
    newObj = {sound = '汪汪'}
    return setmetatable(newObj, {__index = self})
end

我的解决方案的结果是:

wirelessprvnat-172-17-106-141:Programming frankhe$ th test2.lua
Dog=  {
  makeSound : function: 0x0d7f2978
  dog1 : "原始狗类"
  new : function: 0x0d7f2958
}
Dog元表=  nil

myDog=  {
  sound : "汪汪"
}
myDog元表=  {
  __index :
    {
      makeSound : function: 0x0d7f2978
      dog1 : "原始狗类"
      new : function: 0x0d7f2958
    }
}
我说汪汪

我的代码打印了'我说汪汪',并且具有更精确的表结构。我想知道哪个实现是正确的,教程中的还是我的?此外,我还想知道为什么教程中的代码会生成Dog的元表的迭代定义。

点赞