function arguments expected(函数参数期望)

我想通过元表达到一个目的,但我不知道如何正确实现它。更准确地说,我已经实现了它,但我还缺少一个小东西 - 那就是在正确的地方使用冒号。

下面的代码很简单,可以自行理解。我该如何确保Z:Entity.Create()不会导致错误?

Z = {
  Entity = {
    Create = function(name)
      print ('Entity name:', name)
    end,
  }
}

setmetatable(Z.Entity, {__call = function(self, ...)
  print (...)
end})

local p1 = Z:Entity('New entity')  -- table: 0xb8f730 New entity
p1 = Z.Entity.Create('test')  -- Entity name: test
p1 = Z:Entity.Create('test')  -- lua: [string "<eval>"]:16: function arguments expected near '.'

任何建议或帮助都将不胜感激!

原文链接 https://stackoverflow.com/questions/69339074

点赞
stackoverflow用户2858170
stackoverflow用户2858170

a:name()a.name(a)的语法糖。

因此,如果你写Z:Entity.Create('test'),解释器就会期望Entity是一个函数值。但是,括号中预期的函数参数却变成了一个点号。

不过你的代码并不太有意义。为什么你要给p1赋三个不同的值呢?

2021-09-27 06:17:29
stackoverflow用户369792
stackoverflow用户369792

你的代码并不是很自解释,你需要解释你试图做什么以及为什么要使用冒号。我建议你阅读一下该语法,可以通过这个问题了解。冒号基本上是一种调用对象上的函数并将对象作为第一个参数传递的快捷方式。当使用冒号语法定义函数时,它允许你跳过声明“self”参数并在幕后声明一个参数。

让我们看看你的三个示例语句:

第一条语句:

local p1 = Z:Entity('New entity')

这等价于:

local p1 = Z.Entity(Z,'New entity')

由于您为 Z.Entity 设置了元表 __call,因此可以将 Entity 表作为函数调用。由于您使用了冒号语法,因此在调用函数时将 Z 作为第一个参数传递,因此实际上传递了两个参数。然后,以这种方式声明, self 将是 Z.Entity...将扩展为两个参数,即 Z'New entity'

第二条语句:

p1 = Z.Entity.Create('test')

这里你只是调用名为 'Create' 的函数并传递字符串 'test' 打印出 Entity name: test。您没有使用冒号语法,并且元表 __call 函数未被执行,因为你未调用 Entity 如一个函数。

第三条语句:

p1 = Z:Entity.Create('test')
-- lua: [string "<eval>"]:16: function arguments expected near '.'

当你写 Z:Entity 时,它希望你将其作为函数调用,并将 Z 作为该函数的第一个参数传递。在 Entity 后面加上一个点没有任何意义。

可能的假设

从名称 Entity.Create 中,听起来你想要使用此函数创建一个新对象并将其返回。就是你通常会返回一个新表并调用 setmetatable 并指定 __index,它将查找传递的对象以查找可以调用的函数的地方。你应该阅读一下LUA面向对象编程,但是这里是我认为你正在尝试做的快速示例:

Z = {
  Entity = {
    SayHello = function(self)
      print(self.name .. " says 'Hello'!")
    end,

    Create = function(name)
      local obj = {}
      obj.name = name
      setmetatable(obj, {__index = Z.Entity})
      -- 现在你可以调用obj:SayHello()
      return obj
    end
  }
}

local p1 = Z.Entity.Create('Player 1')

-- p1 作为第一个参数传递给SayHello,因为使用了冒号
p1:SayHello()  -- Player 1 says 'Hello'!
2021-10-19 17:09:04