2017-05-19 2 views
0

Perl: rekursive Objektinstanziierung mit Moosen

Im Beispielcode unten, ich definiere eine Klasse Person, die untergeordneten Objekte der gleichen Klasse haben kann.

Wenn ich die printTree Methode aufrufen, erwarte ich die folgende Ausgabe

Sam Ram Geeta 

Was ich stattdessen sehen ist

SamRamRamRamRamRamRamRamRamRamRamR..... 

Irgendwelche Hinweise auf das, was ich falsch mache und wie mein Ziel zu erreichen ?

package Person; 

use Moose; 

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

my @kids; 

sub addChild { 
    my ($self, $name) = @_; 
    my $k = Person->new(name => $name); 
    push @kids, $k; 
    return $k; 
} 

sub printTree { 
    my $self = shift; 
    print $self->name; 
    $_->printTree foreach (@kids); 
} 



no Moose; 

package main; 

my $s = Person->new(name => "Sam"); 
my $r = $s->addChild("Ram"); 
my $g = $s->addChild("Geeta"); 

$s->printTree; 
+1

"printTree" nicht innerhalb von "printTree" aufrufen. Übrigens, sollte '@ kids' nicht auch eine Eigenschaft sein? –

+3

Ihre '@ kids' ist ein Singleton innerhalb der Klasse. Das bedeutet, dass alle Objekte es teilen. Es ist eine schlechte Idee. Es sollte eine Eigenschaft sein. Ich werde später eine Antwort schreiben. – simbabque

Antwort

6

Das Problem ist, dass @Person::kids nicht auf eine Instanz gehört, und Sie effektiv mit am Ende

@Person::kids = ($r, $g); 
$s->printTree() loops through @Person::kids, calls 
$r->printTree() loops through @Person::kids, calls 
    $r->printTree() loops through @Person::kids, calls 
    $r->printTree() loops through @Person::kids, calls 
    ... 

Sie benötigen es, ein Attribut zu machen, z.B.

has kids => (
    isa => 'ArrayRef[Person]', 
    traits => ['Array'], 
    handles => { 
     all_kids => 'elements', 
     push_kids => 'push', 
    }, 
    default => sub { [] }, 
); 
sub addChild { 
    my ($self, $name) = @_; 
    my $k = Person->new(name => $name); 
    $self->push_kids($k); 
    return $k; 
} 
sub printTree { 
    my ($self) = @_; 
    print $self->name; 
    $_->printTree foreach $self->all_kids; 
} 

können Sie perldoc Moose::Meta::Attribute::Native::Trait::Array prüfen für andere nützliche Handgriffe aus dem Array Charakterzug.