首页 > 解决方案 > 如何为角色组编写模块?

问题描述

角色的一个特性是角色组,它允许您声明多个具有相同名称并接受不同参数的角色,类似于多例程:

role Foo[Int:D] {
    method is-int(::?CLASS:_: --> True)  { }
    method is-str(::?CLASS:_: --> False) { }
}
role Foo[Str:D] {
    method is-int(::?CLASS:_: --> False) { }
    method is-str(::?CLASS:_: --> True)  { }
}

通常,对于一种类型,您有一个模块。问题是你在一个模块中只能有一个unit作用域声明,所以你不能将它与角色组一起使用。如何为角色组编写模块?

标签: typesmodulepolymorphismraku

解决方案


您可以拥有没有unit范围声明的模块并从中导出符号,但是如何导出角色组有点问题。您不能为此使用is export特征,因为这将导出错误的类型。当您在声明角色后引用角色时,您指的是角色组,而不是其中的单个角色,但is export在单个角色上使用将导出这些单个角色,而不是角色组。单个角色的 HOW 与角色组非常不同,并且不会像您通常期望的角色那样表现!

EXPORT幸运的是,有一种方法可以使用包来做到这一点。在这个包中声明Foo角色组会给它一个EXPORT::DEFAULT::Foo你可能不想要的名字,所以你需要在MY单元的范围内声明它并为它声明一个常量EXPORT::DEFAULT

use v6.d;

my role Foo[Int:D] {
    method is-int(::?CLASS:_: --> True)  { }
    method is-str(::?CLASS:_: --> False) { }
}
my role Foo[Str:D] {
    method is-int(::?CLASS:_: --> False) { }
    method is-str(::?CLASS:_: --> True)  { }
}

my package EXPORT::DEFAULT {
    constant Foo = ::Foo;
}

现在Foo可以导入使用OK了:

use Foo;

say ::<Foo>:exists;       # OUTPUT: True
say try Foo[1].is-int;    # OUTPUT: True
say try Foo['ok'].is-str; # OUTPUT: True

注意:您不能::在常量名称中使用,因此要在命名空间中导出角色组,您需要将其包装在另一个包中:

my role Foo::Bar[Int:D] { }
my role Foo::Bar[Str:D] { }

my package EXPORT::DEFAULT {
    package Foo {
        constant Bar = Foo::Bar;
    }
}

推荐阅读