Para uma biblioteca que estou escrevendo, tenho um atributo em um HOW que usa a handles
característica para delegar métodos de várias funções executadas por outro COMO ele usa para uma instância desse HOW. Minha primeira tentativa foi assim (embora para facilitar a leitura, isso só lide com isso 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
O problema com isso é que, se algum dos tipos que eu fizer este COMO manipular métodos para sempre mudar, isso não funcionará mais com todos os seus métodos. Então, em vez disso, quero gerar dinamicamente uma lista de métodos que devem ser manipulados, dada uma lista de métodos que este COMO substitui e uma lista de tipos cujos métodos devem ser manipulados. Isso não é tão fácil quanto parece devido à maneira como a handles
característica é implementada. Por exemplo, isso não funcionará:
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 ∌ *)
};
Então, como você geraria dinamicamente um valor para uma característica usar em casos como esse?