使用.does
操作符,我可以检查一个类型是否扮演了我已知的角色。我想获得角色列表。继承有.^mro
,但是在元模型中没有类似于角色的东西。
除此之外,给定一个“类型”,我如何判断它是被定义为类还是角色?
.^roles
say Rat.^roles; # ((Rational[Int,Int]) (Real) (Numeric))
默认情况下,它包括每个角色,包括其他角色引入的角色。要仅获取第一级,请使用:!transitive
Rat.^roles(:!transitive); # ((Rational[Int,Int]))
关于第一个问题已经有了一个很好的答案。对于第二个问题,每个元对象都有一个archetypes
方法,该方法反过来包含由该元类型表示的类型的一系列属性。这是因为Perl 6开放于新的元类型(可以更容易地考虑为“类型的类型”)。可能今天最广泛使用的例子是OO:: Monitors
。原型更关注于人们可以使用该类型做什么。例如:
> role R { }; say "C: {.composable} I: {.inheritable}" given R.HOW.archetypes;
C: 1 I: 0
> class C { }; say "C: {.composable} I: {.inheritable}" given C.HOW.archetypes;
C: 0 I: 1
> Int.HOW.archetypes.^methods(:local)
(nominal nominalizable inheritable inheritalizable composable
composalizable generic parametric coercive definite augmentable)
class C is SomeRole { }
这样的内容时,这就是在幕后发生的事情,这意味着Perl 6不仅开放于新类型的类型,而且这些新类型的类型可以描述它们如何与继承和组合一起工作,如果有的话。does
可组合可能是角色的主要定义属性,因此composable
属性可能是询问“是否为角色”的最佳属性。还可以查看元对象的类型,如另一个答案所建议的那样,但是在表示角色时涉及多个元对象(短名称角色组、该组带参数的柯里化以及单个角色,以及支持组合过程的内部具体化形式)。> say (role RRR[::T] { }).HOW.^name
Perl6::Metamodel::ParametricRoleHOW
> say RRR.HOW.^name
Perl6::Metamodel::ParametricRoleGroupHOW
> say RRR[Int].HOW.^name
Perl6::Metamodel::CurriedRoleHOW
> say (role RRR[::T] { }).HOW.archetypes.composable
1
> say RRR.HOW.archetypes.composable
1
> say RRR[Int].HOW.archetypes.composable
1
.^roles
并指出使用:transitive
选项。 - Jonathan WorthingtonMetamodel::ClassHOW
类型的类型:sub type-classify(Mu \t) {
given t.HOW {
return 'class' when Metamodel::ClassHOW;
return 'role' when Metamodel::ParametricRoleGroupHOW;
}
return 'other';
}
say type-classify(Int); # class
say type-classify(Rational); # role
say type-classify(Bool); # other
MetaModel::ClassHOW
识别。因此,我们可以像这样进行一些黑客操作:role Ur { }
role F does Ur { }
class G does F { }
for Ur, F, G -> $class-or-role {
CATCH {
default {
say "not classy";
}
}
$class-or-role.say;
$class-or-role.^mro.say;
}
将打印:
(Ur)
not classy
(F)
not classy
(G)
((G) (Any) (Mu))
由于在角色上调用^mro
会引发异常,因此可以将其转换为打印哪个是角色,哪个不是的函数。
:transitive
成为默认设置的提交。 - Brad Gilbert