【问题标题】:Lua inheritance override functionLua继承覆盖函数
【发布时间】:2014-10-21 22:25:01
【问题描述】:

我对 Lua 还很陌生,我正在尝试让一个类系统工作。我想做的是有一个基类,它有一堆属性,然后为按钮、文本框等对象扩展这个类。

基类将具有xywidthheight 等属性,然后其他类将具有labelcolour 或类似属性。

如果我在基类上创建了诸如 render() 之类的函数,并在稍后尝试覆盖此函数,它似乎不起作用。 (大概我使用的类完全错误!)

这是我正在使用的复制示例:

Base = {}
Base.__index = Base
function Base.create(value)
    local b = {}
    setmetatable(b, Base)
    b.value = value
    return b
end

function Base:render()
    print("I'm the base! : "..self.value)
end

Button = {}
Button.__index = Base

function Button.create(value)
    local b = Base.create(value)
    setmetatable(b, Button)
    return b
end

function Button:render()
    print("I'm a button! : "..self.value)
end

Button.create("TestBtn"):render()

我希望Button.create("TestBtn"):render() 做的是打印I'm a button! : TestBtn,但它会打印I'm the base! : TestBtn

有人可以帮我用这个新函数覆盖原来的 render 函数吗?

谢谢,威尔。

【问题讨论】:

  • Button.__index = Base 不正确。请注意这与Base.__index = Base 的相同之处
  • @Etan 好的。我认为这就是继承如何发挥它的魔力。那么,我错过了什么或做错了什么?
  • 嗯,所以我觉得我有点突然。这对于将Button 链接到Base 是正确的。问题是您没有在任何东西上使用Button 本身作为__index。我相信你需要setmetatable(b, {__index = Button}) in Button.create。对此感到抱歉。
  • 啊,现在可以了。精彩的。非常感谢 :) 我想我对 __index 和 metatable 的使用有点误解。我最好查一下。如果您想添加您的评论作为答案,我会将其标记为正确。
  • 不,Button.__index = Button 实际上是正确的。这使得Button 类中定义的方法可用于Button.create 中创建的对象(Button 既用作按钮对象的元表,也用作保存按钮方法的表)。缺少的是基类和派生类之间的继承链接:setmetatable(Button, Base)!

标签: inheritance lua


【解决方案1】:

正如@siffiejoe 提到和我暗示的那样,缺少的细节是,正如您所写的那样,您的Button 对象不知道在Button 表中查找方法。

我的解决方案创建了垃圾表来创建该关联,因此并不是最好的解决方案,但说明了这一点。

@siffiejoe 的答案更好,因为它更准确地编码了所需的功能和关系。然后它还需要链接“类”表(即setmetatable(Button, Base))的额外步骤。

这里的关键是index元方法的操作。这在 lua Reference Manual 中用代码描述:

"index": The indexing access table[key].

function gettable_event (table, key)
   local h
   if type(table) == "table" then
     local v = rawget(table, key)
     if v ~= nil then return v end
     h = metatable(table).__index
     if h == nil then return nil end
   else
     h = metatable(table).__index
     if h == nil then
       error(···)
     end
   end
   if type(h) == "function" then
     return (h(table, key))     -- call the handler
   else return h[key]           -- or repeat operation on it
   end
end

【讨论】:

    【解决方案2】:

    定义Button:render 而不是Button:test

    【讨论】:

    • 感谢您的回复。那是我相当愚蠢!但是它似乎仍然运行 Base:render() 代替:codepad.org/AfODqE9J
    猜你喜欢
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    • 2019-06-29
    • 1970-01-01
    • 2020-03-19
    • 2013-06-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多