【问题标题】:How does Raku deal with the diamond problem (multiple inheritance)?Raku 如何处理钻石问题(多重继承)?
【发布时间】:2020-09-23 02:26:32
【问题描述】:

所以 Raku 具有多重继承已经不是什么秘密了,这让我想知道:“Raku 如何以任何合理的方式处理它?”

一些初步测试表明默认行为是从继承列表中的 first 类继承的,这很好,许多其他语言也这样做

class A {
    has $.foo = 0;

    method speak {...}
}

class B is A {
    has $.foo = 1;

    method speak {
        say 'moo';
    }
}

class C is A {
    has $.foo = 2;

    method speak {
        say 'baa';
    }
}

class D is B is C {}

class E is C is B {}

say D.new.foo; # prints 1 (from B)
say E.new.foo; # prints 2 (from C)

但这让我想知道,如果我想让D 使用Cspeak 怎么办? 由于继承顺序,我默认得到 B。

我知道角色的存在是为了通过促进消歧机制来解决这个确切的问题,但假设我发现自己处于没有可供我使用的角色的情况(老板讨厌他们,继承了一个没有拥有它们,选择你的借口)并且真的需要消除继承类的歧义。

Raku 中的处理机制是什么?

【问题讨论】:

    标签: multiple-inheritance raku diamond-problem


    【解决方案1】:

    通常,您需要在具有(潜在)歧义的类中提供一个决胜局方法。幸运的是,您不必创建单独的方法,因为您可以在调用中调用特定版本的方法。

    因此,您的问题的答案是:将方法 speak 添加到 D 类,然后从类 C 中调用 speak 方法:

    class D {
        ...
        method speak { self.C::speak }
    }
    

    对于带参数的方法,取所有参数的Capture,并将其传递:

    class D {
        ...
        method foo(|c) { self.C::foo(|c) }
    }
    

    注意|c 中的“c”只是一个标识符,它可以是任何标识符。但至少对于 Raku 核心开发人员来说,习惯上只使用 |c,其中“c”代表“捕获”。

    现在,这将导致一些开销,因为您会有额外的间接级别。如果这是一个性能问题,您可以进行一些元编程,将D 中的speak 方法别名为C 中的speak 方法:

    class D {
        ...
        BEGIN D.^add_method("speak",C.^find_method("speak"));
    }
    

    由于BEGIN,这将在编译时将Method 对象添加到名为speakD 类,该类由C 类的speak 方法定义。由于这是一个别名,因此您不必担心传递的任何参数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-09
      • 2016-09-21
      • 1970-01-01
      • 2017-05-17
      • 2020-10-03
      • 2017-07-02
      • 2011-02-09
      相关资源
      最近更新 更多