Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Lua:什么时候可以使用冒号语法?_Lua - Fatal编程技术网

Lua:什么时候可以使用冒号语法?

Lua:什么时候可以使用冒号语法?,lua,Lua,虽然我理解基本语法,但我还没有完全弄清楚Lua何时允许使用冒号语法。例如,类似这样的方法确实有效: s = "test" -- type(s) is string. -- so I can write a colon function for that type function string:myFunc() return #self end -- and colon function calls are possible s:myFunc() 然而,同样的模式似乎不适用于其他类型

虽然我理解基本语法,但我还没有完全弄清楚Lua何时允许使用冒号语法。例如,类似这样的方法确实有效:

s = "test"
-- type(s) is string.
-- so I can write a colon function for that type
function string:myFunc() 
  return #self 
end

-- and colon function calls are possible
s:myFunc()
然而,同样的模式似乎不适用于其他类型。例如,当我有一个
而不是
字符串

t = {}
-- type(t) is table.
-- so I can write a colon function for that type
function table:myFunc() 
  return #self 
end

-- Surprisingly, a colon function call is not not possible!
t:myFunc() -- error: attempt to call method 'myFunc' (a nil value)
-- But the verbose dot call works
table.myFunc(t)
转到另一种类型:

x = 1
-- type(x) is number.
-- So I was expecting that I can write a colon function 
-- for that type as well. However, in this case even this
-- fails: 
function number:myFunc() 
  return self 
end
-- error: attempt to index global 'number' (a nil value)
我目前正试图弄明白这一点。得出这样的结论正确吗

  • 某些类型,如
    string
    允许冒号函数定义和冒号函数调用
  • 其他类型,如
    table
    只允许冒号函数定义,不允许冒号函数调用
  • 但其他类型,如
    number
    都不允许

这些差异的具体原因是什么?是否有所有类型的列表,显示它们支持哪种类型的冒号语法?
number
案例是否有解决办法,允许编写例如
x:abs()

关于
string
的第一个示例有效,因为所有字符串共享相同的元表,并且它存储在名为
string
的表中

发件人:

字符串库在表
string
中提供其所有函数。它还为
\u索引
字段指向
字符串
表的字符串设置元表。因此,可以使用面向对象样式的字符串函数。例如,
string.byte(s,i)
可以写成
s:byte(i)


table
上的第二个示例不起作用,因为每个表都有自己的元表,名为
table
的表只是表库所有函数的集合



默认情况下,数字等类型不支持metatable。

作为一个全新的Lua新手,我花了一段时间才理解@Yu Hao的答案,因此我将尝试为其他初学者添加一些细节。如果有什么问题,请纠正我

据我所知,类似于
x:someFunc()
的调用在[*]以下情况下有效:

  • x
    有一个元表
  • 并且元表有一个字段
    \uu索引
  • 它指向一个包含函数
    someFunc
    的表
正如Yu Hao所指出的,字符串自动获得一个指向表
string
的元表,例如:

th> s = 'test'

th> getmetatable(s)
{
  __mod : function: 0x40c3cd30
  __index : 
    {
      upper : function: builtin#82
      rep : function: builtin#79
      split : function: 0x40ffe888
      gfind : function: builtin#87
      find : function: builtin#84
      reverse : function: builtin#80
      lower : function: builtin#81
      len : function: 0x40af0b30
      tosymbol : function: 0x40ffe8a8
      myFunc : function: 0x41d82be0 -- note: this comes from our custom function string:myFunc()
      dump : function: builtin#83
      byte : function: builtin#76
      char : function: builtin#77
      gmatch : function: builtin#87
      match : function: builtin#85
      sub : function: builtin#78
      gsub : function: builtin#88
      format : function: builtin#89
    }
}
因此在本例中,
s:myFunc()
自动工作。为了对
使用冒号语法,我们可以手动设置其元表:

th> function enableColonForTable(t)
..>   meta = {__index = table}
..>   setmetatable(t, meta)
..> end

th> t = {}

th> enableColonForTable(t)

th> t:insert(1) -- works now!
另一个观察结果是,
\u index
是否指向与类型名称完全相同的表实际上并不重要。除了
meta={uuuu index=table}
,我们还可以做:

th> arbitraryScope = {}

th> function arbitraryScope:test() return "something" end

th> t = {}

th> setmetatable(t, {__index = arbitraryScope})
{}

th> t:test()
something   
这也是
数字
的关键区别。虽然有名为
string
table
的现有表,但没有名为
number
的现有表。这就是为什么以前甚至定义函数号:abs()都失败的原因。但我们仍然可以做到:

th> number = {}

th> function number:abs() return math.abs(self) end

th> x = -123

th> debug.setmetatable(x, {__index = number})
-123    

th> x:abs()
123 
注意,我们必须在这里使用
debug.setmetatable
而不是
setmetatable
。两者之间的区别似乎是
setmetatable
仅为给定实例设置metatable,而
debug.setmetatable
为整个类型设置metatable。显然,设定一个新的目标(无论如何也没有多大意义)。这意味着(与表不同)新构造的数字现在默认具有给定的元表,因此:

th> y = -42

th> y:abs()
42  
[*]更新

正如Tom Blodget所指出的,
x:someFunc()
如果
x
本身作为名称空间,也可以工作,即它是一个带有方法字段
someFunc
的表。例如,您可以执行
表:插入(1)
。但是现在名称空间(名为
table
的表)作为
self
传递,您将向名称空间添加数据:

th> print(getmetatable(table)) -- note: "table" does not have a metatable
nil 

th> table:insert(1) -- yet a colon syntax call works

th> table
{
  prune : function: 0x4156bde0
  getn : function: 0x41eb0720
  maxn : function: builtin#90
  remove : function: 0x41eb08c8
  foreachi : function: 0x41eb05b8
  sort : function: builtin#93
  concat : function: builtin#92
  unpack : function: builtin#16
  splice : function: 0x4156bdc0
  foreach : function: 0x41eb0688
  1 : 1
  pack : function: builtin#94
  insert : function: builtin#91
}
补充答覆:

首先,请注意函数是一个值(aka)

是Lua中三个索引操作符之一。索引运算符从对象返回“字段”的值,该对象可以被索引为函数或任何其他类型

按照一般性顺序,索引运算符为:

  • 表达式
    [
    表达式2
    ]
  • 表达式
    标识符
  • 表达式
    标识符
    参数列表
  • 后两种只是“语法糖”,可以用上面任何一种形式重写

    如果“expression2”始终是有效的Lua标识符的同一字符串,并且希望对其进行硬编码,则可以使用第二个

    如果通过索引“identifier”和“expression”返回的值始终是您希望使用“expression”返回的值作为隐式第一个参数调用的函数,则可以使用第三个参数。这种函数调用称为“方法调用”

    另外,请注意,语言/编译器并不关心/知道字段值是否为函数(如果尝试调用非函数的值,则在运行时会出现错误)。它也不关心/知道函数是否是方法(如果不向其传递适当的参数,函数可能不会按照您的预期运行)


    现在,表达式值的类型必须是可以索引的任何类型。请注意,表达式没有编译时类型,因此如果表达式值属于无法索引的类型,这也是一个运行时错误。可索引类型包括:表和具有
    \u索引的任何对象。其他答案提供了这些方面的详细信息

    所以
    string
    是唯一允许这样做的类型?冒号语法是。例如,表支持冒号语法,但并非所有表都有一个通用的元表。@bluenote10,文件句柄是另一个例子。很好的重述,但您缺少