为什么这个点运算符可以工作?

我目前正在按照http://howtomakeanrpg.com/a/classes-in-lua.html上的教程学习关于类的知识,尝试理解冒号运算符的逻辑。据我所知,在函数定义之外,冒号运算符唯一的功能就是将其前面的表作为一个不可见参数传递。

下面我创建了三个不同的怪物来尝试理解这一点。显然我完全不理解这个,因为当我调用第二个怪物时,它不需要我传递表格参数作为Monster(???)。那我为什么可以将monster_3表(我已经测试了它的类型是表格)作为参数输入,Monster:是传入的表吗?还是说只是点号表示Create位于Monster表中。我完全不能理解这点。

我还以为新对象会添加到父表中,但是当我检查monster_(number)是否在表Monster中时,我得到了nill。什么鬼?那么这些新的monster_1, 2, 3表格存储在哪里???

谢谢您的查看,

Xpali

   Monster = {}
function Monster:Create()
    local this =
    {
        name = "orc",
        health = 10,
        attack = 3
    }

    function this:WarCry()
        print(self.name..":GRAAAHH!!!")
    end

    return this

end

monster_1 = Monster:Create()
monster_2 = Monster.Create()
monster_3 = Monster.Create(monster_3)

print(monster_1.name) -- orc
print(type(monster_1)) -- 表格
print(type(Monster.monster_1)) -- nill

print(monster_2.name) -- orc
print(type(monster_2)) -- 表格
print(type(Monster.monster_2)) -- nill

print(monster_3.name) -- orc
print(type(monster_3)) -- 表格
print(type(Monster.monster_3)) -- nill

monster_1:WarCry() -- orc: GRAAAHH!!!
monster_2:WarCry() -- orc: GRAAAHH!!!
    monster_3.WarCry(monster_3) -- orc: GRAAAHH!!!
点赞
用户10805162
用户10805162

代码表现不够明显用于类实例化,因为使用的构造函数没有参数。因此,所有3个实例都是相同的。此外,“Monster.monster_1”等不是实例,而是nil。

为了看到更有趣的东西,我准备了以下代码示例:

-- 默认属性值
local Monster = {
  name = "orc",
  health = 10,
  attack = 3
}

-- 构造函数
function Monster:Create(instance_name)
  -- 从self(即Monster表)获取默认值
  instance_name = instance_name or self.name
  return {
    name = instance_name,
    health = self.health,
    attack = self.attack,
    WarCry = function(this)
      print(this.name .. ": GRAAAHH!!!")
    end
  }
end

monster_1 = Monster:Create()
monster_2 = Monster:Create("named")
--monster_2 = Monster.Create() -- 不正确的用法!
--monster_3 = Monster.Create(monster_3) -- 不正确的用法!

print(monster_1.name) -- orc
print(type(monster_1)) -- table

print(monster_2.name) -- named
print(type(monster_2)) -- table

monster_1:WarCry() -- orc: GRAAAHH!!!
monster_2:WarCry() -- named: GRAAAHH!!!

现在构造函数有一个显式参数("instance_name")和一个隐式参数(Monster table)。后者需要使用“self”关键字。因此,我们在实例化时不应使用点语法,否则会导致错误。如果我们在构造函数定义中避免使用“self”,我们就可以在没有错误的情况下使用点语法,如下所示:

-- 构造函数
function Monster:Create(instance_name)
  -- 从self(即Monster表)获取默认值
  instance_name = instance_name or Monster.name
  return {
    name = instance_name,
    health = Monster.health,
    attack = Monster.attack,
    WarCry = function(this)
      print(this.name .. ": GRAAAHH!!!")
    end
  }
end

monster_1 = Monster:Create()
monster_2 = Monster.Create(nil, "named")

注意最后一次调用中的“nil”。这个参数是必需的,因为构造函数是用冒号语法定义的,但我们使用了点调用。如果省略“nil”参数,则会将“named”值视为冒号上下文中的父表。

附加:

我们还可以使用点语法创建构造函数:

Monster.CreateByDot = function(instance_name)
  instance_name = instance_name or 'Noname';
  return {
    name = instance_name,
    WarCry = function(this)
      print(this.name .. ": GRAAAHH!!!")
    end
  }
end

monster_3 = Monster.CreateByDot()
monster_4 = Monster.CreateByDot('Fourth')

monster_3:WarCry() -- Noname: GRAAAHH!!!
monster_4:WarCry() -- Fourth: GRAAAHH!!!

并看到参数“instance_name”的效果。

2018-12-25 15:25:40