【问题标题】:Overwrite function only for a particular instance in LUA仅针对 LUA 中的特定实例的覆盖功能
【发布时间】:2019-07-02 16:21:56
【问题描述】:

我基本上不会寻找有关如何做某事的答案,但我找到了如何做,但想要更多信息。希望这种问题在这里是可以的。 因为我刚刚发现了我正在修改的游戏代码,所以我不知道我应该用谷歌搜索什么。

在 Lua 中,我可以有例如:

Account = {balance = 0}
function Account.withdraw (v)
     self.balance = self.balance - v
end

我可以(在另一个 lua 文件中)

function Account.withdrawBetter (v)
    if self.balance > v then 
      self.balance = self.balance - v
    end
end

.... -- 在某个函数的某个地方,带有一个 Account 实例: a1.withdraw = a1.withdrawBetter `

这种“技术”的名称是什么,以便我可以找到有关它的更多信息(可能的陷阱、性能考虑与覆盖/覆盖等)?请注意,我只为特定实例 (a1) 更改 withdraw,而不是为每个 Account 实例更改。

额外问题:任何其他具有这种功能的 oo 编程语言?

谢谢

【问题讨论】:

    标签: function object lua overriding overwrite


    【解决方案1】:

    Lua 中的面向对象

    首先需要指出的是,Lua 并没有实现面向对象编程;它没有对象、类、继承等概念。

    如果你想在 Lua 中实现 OOP,你必须自己实现它。通常这是通过创建一个充当“类”的表来完成的,存储“实例方法”,这些方法实际上只是接受实例作为其第一个参数的函数。

    然后通过让“构造函数”(也只是一个函数)创建一个新表并将其元表设置为一个具有指向类表的__index 字段来实现继承。当使用它没有的键索引“实例”时,它将在类中搜索该键。

    换句话说,一个“实例”表可能根本没有任何功能,但是使用例如"withdraw" 对其进行索引只会尝试对类进行索引。

    现在,如果我们获取一个“实例”表并为其添加一个withdraw 字段,Lua 将看到它具有该字段,而无需费心在类中查找它。你可以说这个值遮蔽类表中的那个。

    这个“技术”叫什么名字

    实际上并没有,但您绝对应该研究元表。

    确实支持此类事情的语言中,例如在 Ruby(见下文)中,这通常是使用单例类完成的,这意味着它们只有一个实例。

    性能考虑

    索引表(包括元表)需要一些时间。如果 Lua 在实例表中找到一个方法,那就是单表查找;如果没有,则需要首先获取元表和索引,如果它也没有它并且有自己的元表,那么链就这样继续下去。

    所以,换句话说,这实际上是更快。它确实占用了更多空间,但实际上并没有那么多(技术上它可能会很多,但你真的不应该担心这一点。尽管如此,here's where you can read up on that,如果你愿意) .

    还有其他具有这种功能的 oo 编程语言吗?

    是的,很多。 Ruby 就是一个很好的例子,你可以在其中做类似的事情

    array1 = [1, 2, 3]
    array2 = [4, 5, 6]
    
    def array1.foo
      puts 'bar'
    end
    
    array1.foo # prints 'bar'
    array2.foo # raises `NoMethodError`
    

    【讨论】:

    • 我知道您发布的 Lua 中有关 OO 的注意事项,但也感谢您。当您说它没有名称时,您的意思是在 Lua 中没有名称,甚至在 Rubi 中都没有,我觉得即使 foo 是一种方法,覆盖也不合适?我实际的 OO 经验是 Java。
    • @LucianHada Overriding 是一个很好的描述,我会用谷歌搜索它,但它的 name 并不多。正如我所说,singleton classes 是“真正的”OOP 中的一个相关概念,但 Lua 使用类似原型的方法,其中类和对象之间的界限实际上只是在程序员的头脑中。在某种程度上,每个对象都是它自己的一个子类,所以这广泛地属于“子类型化”,尽管这是一种非常不方便的思考方式。
    • 在这一点上,我看不到单例和 this 之间的联系,但也许是我的错,我会更深入地研究它。可能有由引擎创建的帐户的 a1、a2 等实例(是的,我正在修改的游戏是在 Lua 上实现 OOP)访问一个或多个此类实例并以这种方式“覆盖”其中一种方法(不影响其他实例)
    • 我的困境(性能、陷阱等)实际上是如果在条件变为真时在“对象”上使用这种技术,然后在条件变为假时恢复到原始函数/方法而不是更多覆盖“类方法”的经典方法并检查我的实现中的条件(如果条件=false则调用原始函数)
    • 获取原始方法,使用您的条件创建一个新函数并存储它(因此它只关闭一次),然后将其添加到您要覆盖的实例中并保持原样。这应该是最可靠的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-19
    • 2015-05-14
    • 2016-08-24
    • 1970-01-01
    • 2019-02-24
    • 2020-09-28
    相关资源
    最近更新 更多