Going over the Bridge, part 1

在处理 Raku 中的数字的类中,我们看到了 Bridge 方法,该方法以多态方式使用。让我们花一些时间,并试图了解 1)它是如何工作的,2)是否有必要。

类和角色

我们的第一步是查看方法定义在哪里。以下是我们需要的类和角色列表:

  • Duration
  • Instant
  • Int
  • Num
  • Rational
  • Real

为了预测下一步,让我们添加一些关于他们关系的更多细节:

  • class Duration is Cool does Real
  • class Instant is Cool does Real
  • class Int is Cool does Real
  • class Num is Cool does Real
  • role Rational does Real
  • role Real does Numeric

在斜体字体中,我添加了伪声明,这些伪声明没有在 src/core 的相应文件中明确拼写,而是通过 src/Raku/Metamodel/BOOTSTRAP.nqp 设置:

Int.HOW.add_parent(Int, Cool);
. . .
Num.HOW.add_parent(Num, Cool);

对于完整的图片,我们可以查看其他类的位置,例如 RatComplex,但让我们先关注上面的列表。

Bridge 方法

现在,让我们看看这些类和角色中 Bridge 方法的定义。

这两个类, DurationInstand 与其他类有些区别,因为它们代表时间而不是数字(当然,时间用数字表示)。 Bridge 方法的定义方式如下(在本文和下面的节选中,通过查看参数的类型,可以很容易地看到方法的定义类):

method Bridge(Duration:D:) { $!tai.Num }

method Bridge(Instant:D:) { $!tai.Bridge }

$!tai 类属性是一个 Rat 数字,它保存着了自 1970 年以来的秒数。

好吧,转到数字。对于 Num 类和 Real 角色,没有注释:

method Bridge(Num:D:) { self }

method Bridge(Real:D:) { self.Num }

Rational 角色中的定义看起来有点突出,并且不包含明确的参数,因此它可以接受定义的和未定义的调用者:

method Bridge() { self.Num } # Rational role

最后,Int 类使用 NQP 构建桥:

method Bridge(Int:D:) {
    nqp::p6box_n(nqp::tonum_I(self));
}

它将 Int 数字转换为原生数字,并将其解包为 Raku Num 值。这很重要,我们应该在 REPL 输出中看到它,例如:

$ raku 
To exit type 'exit' or '^D'
> Int.new.Bridge.WHAT;
(Num)

所以,来自 Int 的桥是 Num。其实,其他桥梁也给我们相同的数据类型。从我们刚刚看到的方法的定义中可以清楚地看到它。唯一的例外是 Instant 类:它在 Rat 值上调用 .BridgeRat 类没有定义方法,但它是从 Rational 角色继承的:

my class Rat is Cool does Rational

我们知道该角色的方法返回 self.Num

感觉头晕?让我们休息一下,继续下一篇文章。

Raku 

comments powered by Disqus