LED*_*tom 2 lua namespaces metatable meta-method
我对使用"."的以下两种语法感到困惑.
根据我的理解,__index当一个键不存在于表中但存在于其元表中时调用.那么为什么列表会调用__index然后将其自身分配给list.__index?
list = {}
list.__index = list
setmetatable(list, { __call = function(_, ...)
local t = setmetatable({length = 0}, list)
for _, v in ipairs{...} do t:push(v) end
return t
end })
function list:push(t)
if self.last then
self.last._next = t
t._prev = self.last
self.last = t
else
self.first = t
self.last = t
end
self.length = self.length + 1
end
.
.
.
local l = list({ 2 }, {3}, {4}, { 5 })
Run Code Online (Sandbox Code Playgroud)是否Window.mt只需创建一个表?为什么我们需要Window = {}在这里作为命名空间?
Window = {} -- create a namespace
Window.mt = {} -- create a metatable
Window.prototype = {x=0, y=0, width=100, height=100, }
function Window.new (o)
setmetatable(o, Window.mt)
return o
end
Window.mt.__index = function (table, key)
return Window.prototype[key]
end
w = Window.new{x=10, y=20}
print(w.width) --> 100
Run Code Online (Sandbox Code Playgroud)列表调用时, 代码中没有任何地方__index.然而,赋值部分是一个常见的Lua习语(又名.hack)来节省一些内存.从概念上讲,涉及4种不同的表格:
{length=0}代码创建的表)__index字段),当您尝试访问对象中不存在的字段时,它会修改列表对象的行为list类,它包含所有用于列表对象的方法(如push方法),并且还用作用于列表对象构造该类的metatable(包含一个__call字段)list,以便您可以像调用list函数一样调用该表

由于metatable字段始终以两个下划线(__)开头,而普通方法通常不会,因此您可以将metatable字段和常规方法并排放入单个表中而不会发生冲突.这就是这里发生的事情.在list类表还提供了列表对象的元表.因此,使用此技巧可以节省通常需要用于单独metatable的内存(x86-64 Linux上Lua 5.2的字节大小显示在表标题栏的方括号中,顺便说一句.):

不,{}创建一个表.然而,这个新表下键保存"mt"在Window表中,可能给这个用户的Window"类"直接访问的元表所使用的窗口对象.只给出您显示的代码,这不是绝对必要的,您可以使用局部变量.
原则上,你可以存储Window.mt,Window.new和Window.prototype单独的,但会很麻烦,如果你有多个"类"之类Window.这样你可以避免名字冲突,并使用Window"类"看起来更好.
另一个原因可能是,require只能从模块定义返回一个值,如果你要导出多个值(例如new,mt和prototype)由一个模块,你需要一个表来包装在一起(或使用全局变量,但被认为是坏风格).
| 归档时间: |
|
| 查看次数: |
319 次 |
| 最近记录: |