2010-12-14 15 views
3

ich Moose (insbesondere MooseX::Declare) unter Verwendung ein Iterator-Objekt zu erstellen, die eine Iternext Methode, Zustand und gibt 01 oder je nach Bedarf in einer while Anweisung zur Verwendung vorrückt hat. Das Problem, auf das ich stoße, ist, dass next abhängig von der Existenz eines der Konstruktionsparameter zwei sehr unterschiedliche Operationen ausführen muss. So wie ich es sehe ich habe fünf Optionen:Wie kann man einen Methodenkörper zur Konstruktionszeit am besten zuweisen, wenn man Moose verwendet?

  1. wenn ... dann in next Methode
  2. Unterklasse
  3. Hash-Versand
  4. Symboltabelle Manipulation
  5. Put-Methoden in verschiedenen Modulen und Last erforderlich eine an Bauzeit ist

Nummer 1 nur Amateur.

Nummer 2 ist, denke ich, die richtige OOP Art und Weise Dinge zu tun. Ich habe keine Einwände dagegen, es so zu machen, aber es scheint ein wenig übertrieben zu sein, einfach eine einzige Methode zu übergehen.

Ich habe oft Nummer 3 in der Vergangenheit verwendet, wenn prozedural oder pseudo-funktional arbeiten und es ist, was ich gerade mache.

Nummer 4 ist, wie wir alle wissen, voller Gefahr und ich weiß nichts über Elch-Eingeweide zu wollen beginnen herumspielen, wenn unnötig.

Das letzte Element, Nummer 5 scheint mir die vernünftigste (und Perl) aber wie Nummer 2, ist ein wenig zu viel Arbeit. Ich frage mich wirklich, ob es eine fünfte Möglichkeit gibt, die ich nicht in Betracht gezogen habe, wie zum Beispiel in die Metaklasse zu haken oder vielleicht ein MooseX Modul, das einigermaßen reif ist.

+0

Sie könnten weiter wollen erklären, was sollten die verschiedenen Aktionen sind, dass der Iterator durchführen. Es ist schwierig, Design-Ratschläge zu geben, ohne den vollen Anwendungsfall zu kennen. – phaylon

+0

Nun, ich bin wirklich auf der Suche nach einer Best Practice und nicht Implementierungsdetails. Was ich gerade gut mache, aber ist Hash-Dispatching wirklich will ich im 'Moose'-Paradigma machen? Das ist der "Moosy" Weg, dies zu tun? – gvkv

Antwort

10

Fahren Sie mit ‚Weiter‘ Subref in den Konstruktor und speichern Sie sie in einem Attribut:

has next => (
    isa => 'CodeRef', 
    required => 1, 
    traits => ['Code'], 
    handles => { next => 'execute_method' }, 
); 

Mit dem ‚execute_method‘ Handler vom native attribute 'Code' trait bereitgestellt, können Sie rufen Sie die ‚next‘ Methode als ein normales Verfahren und es wird den Subref-Body im Attribut finden.

Wenn Sie möchten, um die Subref Körper/n vordefinieren und Bauzeit entscheiden, welche Version zu verwenden, können Sie den Wert von ‚next‘ in einem Builder Untersatz nach anderen Bedingungen des Objekts:

has next => (
    # ... 
    lazy => 1, 
    default => sub { 
     my $self = shift; 
     return sub { ... } if $self->some_condition; 
     # etc etc... 
    }, 
); 
+3

Um es für jeden, der dies liest, explizit zu machen, ist die Tatsache, dass es kein 'is => '..'', 'reader' oder' accessor' gibt, beabsichtigt. Es ist sehr elegant, der delegierten Methode den gleichen Namen wie dem Attribut zu geben - sie bietet genau die benötigte Funktionalität mit einem Minimum an möglicher Verwirrung. – hdp

0

ist eine weitere Option dynamisch eine Rolle anzuwenden:

package Iter; 
use Moose; 
use Moose::Util qw(apply_all_roles); 

has next_role => (is => 'ro'); 

sub BUILD { 
    my $self = shift; 
    apply_all_roles($self, $self->next_role); 
} 
Verwandte Themen