Lua:什么时候可以使用冒号语法?
虽然我理解基本语法,但我还没有完全弄清楚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() 然而,同样的模式似乎不适用于其他类型
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
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]
标识符:
标识符(
参数列表)
现在,表达式值的类型必须是可以索引的任何类型。请注意,表达式没有编译时类型,因此如果表达式值属于无法索引的类型,这也是一个运行时错误。可索引类型包括:表和具有
\u索引的任何对象。其他答案提供了这些方面的详细信息 所以string
是唯一允许这样做的类型?冒号语法是。例如,表支持冒号语法,但并非所有表都有一个通用的元表。@bluenote10,文件句柄是另一个例子。很好的重述,但您缺少