Esistono alcuni modi per fornire l'estensibilità; consentire all'utente di applicare i ruoli alla classe, o consentire loro di passare in piccoli oggetti che fanno le cose interessanti (delegati). I delegati si comportano meglio dei ruoli, ma richiedono di pianificare tutta l'estensibilità in anticipo. I ruoli consentono comportamenti più ad-hoc.
Ecco due distribuzioni CPAN che prendono ogni approccio:
delegati: AnyEvent::Subprocess
ruoli: Devel::REPL
ruoli plugin sono implementate tramite MooseX::Object::Pluggable.
I delegati sono implementati come preferisci; il modello sta passando un'istanza di una classe A che fa qualche ruolo R alla classe C, e quindi di classe C delegati al A. Ecco un esempio:
package Compare;
use Moose::Role;
requires 'compare';
package SpaceshipCompare;
use Moose;
with 'Compare';
sub compare { my ($a, $b) = @_; return $a <=> $b }
package Sort;
use Moose;
has 'comparer' => (
is => 'ro',
does => 'Compare',
handles => 'Compare',
required => 1,
);
sub my_sort {
my ($self, @list) = @_;
return sort { $self->compare($a, $b) } @list;
}
quindi si utilizza questo tipo:
my $sorter = Sort->new(comparer => SpaceshipCompare->new);
my @sorted = $sorter->my_sort("1one", "0", "43");
Se si desidera che il metodo Sort funzioni, è sufficiente creare una nuova classe con il ruolo Compare
e quindi passare un'istanza al costruttore di Sort. Flessibilità istantanea!
Hai esaminato [Module :: Pluggable] (http://search.cpan.org/~simonw/Module-Pluggable-3.9/lib/Module/Pluggable.pm)? –
@Len Ho dato un'occhiata a diversi moduli in una volta, ma preferirei imparare dall'esperienza comunitaria. Penso di averne trovato almeno 3 diversi e di aver letto anche altri modi. Non so perché esistano così tanti modi e quale sia la differenza. TIMTOWTDI, ma di solito c'è una ragione per cui esiste più di un modo. – xenoterracide