为什么.__index只返回子类中的函数而不是基类中的函数?

3
item = {y = 21}

function item:new(o)
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    return o
end

function item:Run()
    print("item running")
end

berry = item:new{x = 52}

function berry:new(o)
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    return o
end
function berry:Run()
    print("berry is running")
    self.__index:Run()
end

berry:new{b = 32}:Run()

当应该打印“berry is running”后面跟着“item running”时,输出会无限地打印“berry is running”。即使我将self.__index 改为 self.__index.__index 或者甚至是 self.__index.__index.__index,输出仍然会无限地打印“berry is running”。我该如何纠正这个问题呢?非常感谢您的帮助。

ه°†self.__index:Run()و›؟وچ¢ن¸؛getmetatable(self):Run() - Egor Skriptunoff
@EgorSkriptunoff “item running” 只被打印一次,但“berry is running” 被打印了两次而不是一次。如果我从 berry 创建一个进一步的子类,这仍然有效吗? - Shabbs15
我的 Run() 方法在层次结构中的每个级别上都会被执行一次。这就是为什么会有三条消息:来自子类、来自 berry 类和来自 item 类。 - Egor Skriptunoff
1个回答

0
你已经覆盖了你的berryitemRun函数,这使得访问它更加困难。此覆盖导致无限循环,因为self.__index是对self(一个berry)的引用。现在,在berry中定义了Run,当使用Run索引berry时,将不再调用__index
所以你的berry:Run函数本质上是:
function berry:Run()
    print("berry is running")
    berry:Run()
end

我建议您更改berry:Run函数,并在其中特别调用item.Run

function berry:Run()
    print("berry is running")
    item.Run(self) -- specifically call item.Run and pass it self.
end

这将会给你所需的输出结果:

berry 正在运行

item 正在运行


或者,您可以通过在 Run 之前在 berry 中定义它来保留 item:Run 函数:

berry.ParentRun. = berry.Run -- this will cause __index to run and get item:Run
function berry:Run()         -- This now defines berry.Run. now __index will no longer run for berry.Run
    print("berry is running")
    self:ParentRun()         
end

额外提示:

你看到的原因是

berry 正在运行

berry 正在运行

item 正在运行

来自评论中的建议,是因为运行的顺序将会是

object:Run() -- this calls berry passing the self of object

打印我们的第一个berry正在运行

现在,我们获取该对象(即berry)的元表,并调用它的run方法。

berry:Run()

打印我们的第二个berry正在运行

最后,我们获取berry的元表,即item,并调用它的run函数

item:Run()

打印正在运行的项目


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接