2017-10-16 3 views
1

Bisher habe ich mich immer auf die Reihenfolge der Variablen in einer Klasse verlassen, aber jetzt versuche ich, diese Variablen in einer gemischten Reihenfolge zu initialisieren.Wie initialisiert man eine bestimmte Klassenvariable beim Erstellen eines Objekts?

Zum Beispiel, das ist, was ich normalerweise beim Erstellen eines Objekts tun.

my $person1 = Person->new ('Fernando', 'Alonso', 36); 

Und das ist, was ich versuche zu erreichen.

my $person2 = Person->new (Age => 36, FistName => 'Fernando', LastName => 'Alonso'); 

Ich versuchte => in Bezug auf mehrere Dokumente (z perldoc) Ich sah, aber sie haben ein komplettes Beispiel für mich nicht zurück. Allerdings arbeite ich nicht am folgenden Skript, es ist ein fairer MCVE mit dem 'Klischee' Paket Person.

use strict; 
use warnings; 

package Person; 
sub new { 
    my $class = shift; 
    my $self = { 
    FirstName => shift, 
    LastName => shift, 
    Age  => shift, 
    }; 
    print "First name : $self->{FirstName}\n"; 
    print "Last name : $self->{LastName}\n"; 
    print "Age  : $self->{Age}\n\n"; 
    bless $self, $class; 
    return $self; 
} 

# Works well 
my $person1 = Person->new ('Fernando', 'Alonso', 36); 

# (?) How to assign 36 directly to $self->{Age} 
my $person2 = Person->new (Age => 36, '', ''); 

Der Ausgang ist wie folgt.

First name : Fernando 
Last name : Alonso 
Age  : 36 

First name : Age 
Last name : 36 
Age  : 

Also, wie soll ich das Objekt erstellen, um explizite Zuordnungen zu den Klassenvariablen zu machen? Falls erforderlich, wie soll ich das Paket Person ändern?

P.S. Ich vermeide es, die Variablen zu ändern, nachdem das Objekt erstellt wurde.

Antwort

5

Der ursprüngliche Klassenkonstruktor Person erwartet, dass die Argumente Werte in einer bestimmten Reihenfolge enthalten, Sie jedoch Schlüssel/Wert-Paare angeben möchten. Dies ist einfach genug, indem die Eingabe als Hash-Referenz dargestellt wird.

package Person; 
sub new { 
    my $class = shift; 

    # read @_ as list of key-value pairs; 
    # set $self as reference to hash of these pairs 
    my $self = { @_ };  
    #my $self = { my %args = @_ }; # if you like your abstractions unbroken 

    bless $self, $class; 
    return $self; 
} 

Wenn Sie die Schlüssel beschränken möchten, die FirstName eingestellt werden kann, LastName und Age, Sie so etwas tun könnte.

package Person; 
sub new { 
    my $class = shift; 
    my %args = @_; 
    my $self = { 
    FirstName => $args{FirstName}, 
    LastName => $args{LastName}, 
    Age  => $args{Age}, 
    }; 
    bless $self, $class; 
    return $self; 
} 

und als eine weitere Verbesserung, können Sie die Standardwerte zur Verfügung stellen, wo der Anrufer alle erwarteten Schlüssel nicht

package Person; 
sub new { 
    my $class = shift; 
    my %args = @_; 
    my $self = { 
    FirstName => $args{FirstName} // "Fred", 
    LastName => $args{LastName} // "Flinstone", 
    Age  => $args{Age} // 42, 
    }; 
    bless $self, $class; 
    return $self; 
} 
+3

angegeben ... und wenn Sie gegen Tippfehler robust sein möchten, können Sie '$ löschen args {$ key} 'jedes Argument, so dass Sie anschließend nach unbenutzten Argumenten wie' if (my @unknown = Sortierschlüssel% args) suchen können {krächzen "Unbekannte benannte Argumente: @unknown"; } ' – amon

+0

Ich versuchte beide Lösungen und beide funktionierten perfekt. – ahmedus

+0

'my $ self = {@_}' bricht die Abstraktion. Ich denke, du solltest es zumindest als unerwünscht bezeichnen. – Borodin

Verwandte Themen