Для библиотеки, которую я пишу, у меня есть атрибут в 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
Проблема с этим заключается в том, если какой-либо из типов, которые я делаю, это КАК обрабатывать методынавсегда изменения, это больше не будет работать со всеми их методами. Поэтому вместо этого я хочу динамически генерировать список методов, которые должны быть обработаны, учитывая список методов, которые это КАК переопределяет, и список типов, чьи методы должны быть обработаны. Это не так просто, как кажется, из-за того, как реализована черта 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 ∌ *)
};
Итак, как бы вы динамически сгенерировали значение для черты для использования в подобных случаях?