gpt4 book ai didi

lua - Lua 中使用 "."表示法与 __index 和命名空间的混淆

转载 作者:行者123 更新时间:2023-12-02 18:14:58 26 4
gpt4 key购买 nike

我对以下两种使用“.”的语法感到困惑

  1. 据我了解,当键不存在于表中但存在于其元表中时,会调用 __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 })
  2. 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

最佳答案

那么为什么简单表会调用__index,然后将自己赋值给list.__index呢?

代码中没有任何地方调用__index。然而,赋值部分是一个常见的 Lua 习惯用法(又名 hack),用于节省一些内存。从概念上讲,涉及 4 种不同类型的表:

  1. 列出对象(通过代码中的 {length=0} 创建的表)
  2. 元表(包含 __index 字段),当您尝试访问对象中不存在的字段时,该元表会修改列表对象的行为
  3. list 类,它包含列表对象的所有方法(如 push 方法),并且还充当列表对象的构造函数
  4. list 类的元表(包含 __call 字段),以便您可以像调用 list 表一样这是一个函数

    list objects separate metatable and index table

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

list objects with merged metatable and index table

Window.mt 只是创建一个表吗?

否,{} 创建一个表。但是,这个新表保存在 Window 表中的键 "mt" 下,可能是为了让这个 Window “类”的用户直接访问到用于窗口对象的元表。仅给出您展示的代码,这并不是绝对必要的,您可以使用局部变量来代替。

为什么我们需要 Window = {} 作为此处的命名空间?

原则上,您可以单独存储 Window.mtWindow.newWindow.prototype,但是如果你有多个“类”,例如Window。这样您就可以避免名称冲突,并且使用Window“class”看起来更好。

另一个原因可能是 require 只能从模块定义返回单个值,如果您想导出多个值(例如 newmt prototype),您需要一个表将它们包装在一起(或使用全局变量,但这被认为是不好的风格)。

关于lua - Lua 中使用 "."表示法与 __index 和命名空间的混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27519842/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com