私が書いているライブラリの場合、そのHOWの属性をhandles
使用して、そのHOWのインスタンスに、別のHOWが実行するさまざまな役割のメソッドを委任します。私の最初の試みはこのように見えました(これを読みやすくするために、これはのみを扱いますMetamodel::Naming
):
class ParentHOW does Metamodel::Naming {
method new_type(ParentHOW:_: Str:D :$name!, Str:D :$repr = 'P6opaque' --> Mu) {
my ::?CLASS:D $meta := self.new;
my Mu $type := Metamodel::Primitives.create_type: $meta, $repr;
$meta.set_name: $type, $name;
$type
}
}
class ChildHOW {
has Mu $!parent;
has Mu $!parent_meta handles <set_name shortname set_shortname>;
submethod BUILD(ChildHOW:D: Mu :$parent is raw) {
$!parent := $parent;
$!parent_meta := $parent.HOW;
}
method new_type(ChildHOW:_: Mu :$parent is raw) {
my ::?CLASS:D $meta := self.new: :$parent;
Metamodel::Primitives.create_type: $meta, $parent.REPR
}
method name(ChildHOW:D: Mu \C --> Str:_) { ... }
}
my Mu constant Parent = ParentHOW.new_type: :name<Parent>;
my Mu constant Child = ChildHOW.new_type: :parent(Parent);
say Child.^shortname; # OUTPUT: Parent
これの問題は、私がこのHOWハンドルメソッドを作成するタイプのいずれかがこれまでに変更された場合、すべてのメソッドで機能しなくなることです。したがって、代わりに、このHOWがオーバーライドするメソッドのリストと、メソッドを処理する必要がある型のリストを指定して、処理する必要があるメソッドのリストを動的に生成したいと思います。handles
トレイトがどのように実装されているかにより、これは思ったほど簡単ではありません。たとえば、これは動作しません:
has Mu $!parent_meta handles do {
my Array[Str:D] constant PARENT_METHOD_OVERRIDES .= new: <name>;
((), Metamodel::Naming)
.reduce({ (|$^methods, |$^role.HOW.methods: $^role) })
.map(*.name)
.grep(PARENT_METHOD_OVERRIDES ∌ *)
};
では、このような場合に使用する特性の値を動的にどのように生成しますか?