在处理 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);
对于完整的图片,我们可以查看其他类的位置,例如 Rat
或 Complex
,但让我们先关注上面的列表。
Bridge 方法
现在,让我们看看这些类和角色中 Bridge
方法的定义。
这两个类, Duration
和 Instand
与其他类有些区别,因为它们代表时间而不是数字(当然,时间用数字表示)。 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
值上调用 .Bridge
。 Rat
类没有定义方法,但它是从 Rational
角色继承的:
my class Rat is Cool does Rational
我们知道该角色的方法返回 self.Num
。
感觉头晕?让我们休息一下,继续下一篇文章。