2010-11-19 7 views
6

Ich habe ein paar träge Funktionen in einem Moose-Objekt.Wie kann ich alle faulen Moose-Funktionen erstellen?

Einige der Erbauer benötigen etwas Zeit, um zu beenden.

Ich möchte alle Builder (die Dump das "bomplete" -Objekt) nvoke. Kann ich alle Lazy-Features gleichzeitig erstellen oder muss ich jedes Feature manuell aufrufen, damit der Builder ausgeführt wird?

+1

Sollten Sie 'default' nicht für das verwenden? Ich dachte, der Punkt von "faul" war, die Erstellung des Attributwerts bis zur ersten Verwendung zu verschieben. Wenn Sie bei der Konstruktion von Objekten alle Attribute festlegen müssen, scheint 'default' sinnvoller zu sein. Oder Sie können Ihre eigene BUILD-Methode angeben. –

+0

Dies ist ein relativ gebräuchliches Idiom und es gibt einige gute Gründe dafür. – hobbs

+0

Grundsätzlich könnten Sie alle Arbeiten in 'BUILD' erledigen, aber es ist schöner, eine Methode pro Attribut zu haben. Und wenn Sie eine Methode pro Attribut haben, um den Wert zu berechnen, dann kann es auch ein Builder sein. Wenn ein Builder jedoch auf andere Attribute zugreift, muss das erstellte Attribut träge sein, um sicherzugehen, dass sie initialisiert wurden. Und es gibt keine "faul, aber nur ein * bisschen * faul" Attribut Option :) – hobbs

Antwort

6

Wenn Sie "faule" Attribute mit Buildern haben möchten, aber sicherstellen, dass ihre Werte erstellt werden, bevor new zurückgibt, ist es üblich, die Accessoren in BUILD aufzurufen.

sub BUILD { 
    my ($self) = @_; 

    $self->foo; 
    $self->bar; 
} 

ist genug, um den Job zu erledigen, aber es ist wahrscheinlich am besten, um einen Kommentar hinzufügen, auch diesen scheinbar nutzlosen Code jemand erklären, der nicht das Idiom nicht kennt.

3

Vielleicht könnten Sie die Meta-Klasse verwenden, um eine Liste von 'faulen' Attributen zu erhalten. Zum Beispiel:

package Test; 

use Moose; 


has ['attr1', 'attr2'] => (is => 'rw', lazy_build => 1); 
has ['attr3', 'attr4'] => (is => 'rw',); 

sub BUILD { 
    my $self = shift; 


    my $meta = $self->meta; 

     foreach my $attribute_name (sort $meta->get_attribute_list) { 

     my $attribute = $meta->get_attribute($attribute_name); 

     if ($attribute->has_builder) { 
      my $code = $self->can($attribute_name); 
      $self->$code; 

     } 
    } 

} 


    sub _build_attr1 { 1 } 
    sub _build_attr2 { 1 } 
2

ich genau dieses Erfordernis mehrmals in der Vergangenheit und heute habe hatte ich es tatsächlich von den Metaklasse zu tun, die keine BUILD Zwicken gemeint erlaubt. Auf jeden Fall fühlte ich, es wäre gut, zu teilen, da es genau im Grunde tut, was Äther erwähnt:

‚würde es erlauben Attribute„Markierung dieses faul ist, weil es auf andere Attributwerte ist abhängig gebaut werden, aber ich will . es vor Bau abgeschlossen stocherte werden "‘

jedoch Derp Derp ich keine Ahnung, wie so hier ein CPAN-Modul zu machen sind einige Codes: https://gist.github.com/TiMBuS/5787018

Setzen sie die oben in Late.pm und dann kannst du i benutzen t mögen so:

package Thing; 
use Moose; 
use Late; 

has 'foo' => (
    is  => 'ro', 
    default => sub {print "setting foo to 10\n"; 10}, 
); 

has 'bar' => (
    is  => 'ro', 
    default => sub {print 'late bar being set to ', $_[0]->foo*2, "\n"; $_[0]->foo*2}, 
    late => 1, 
); 

#If you want.. 
__PACKAGE__->meta->make_immutable; 
1; 


package main; 

Thing->new(); 
#`bar` will be initialized to 20 right now, and always after `foo`. 
#You can even set `foo` to 'lazy' or 'late' and it will still work. 
Verwandte Themen