2017-10-16 3 views
1

Jusqu'ici je me suis toujours appuyé sur l'ordre des variables dans une classe, mais maintenant j'essaye d'initialiser ces variables dans un ordre mélangé.Comment initialiser une variable de classe spécifique lors de la création d'un objet?

Par exemple, c'est ce que je fais normalement lors de la création d'un objet.

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

Et c'est ce que j'essaie d'atteindre.

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

J'ai essayé => en ce qui concerne plusieurs documents (par exemple perldoc) j'ai vu, mais ils ne sont pas revenus un exemple complet pour moi. Cependant, je ne travaille pas vraiment sur le script suivant, c'est un MCVE juste avec le paquet 'cliché' 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, '', ''); 

La sortie est la suivante. Alors, comment dois-je créer l'objet pour faire des affectations explicites aux variables de classe? Si nécessaire, comment modifier le paquet Person?

P.S. J'évite de changer les variables après la création de l'objet.

Répondre

5

Le constructeur de classe Person d'origine s'attend à ce que les arguments contiennent des valeurs dans un ordre spécifique, mais vous souhaitez spécifier des paires clé-valeur. C'est assez facile en représentant l'entrée comme une référence de hachage.

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; 
} 

Si vous voulez limiter les clés qui peuvent être réglées à FirstName, LastName et Age, vous pouvez faire quelque chose comme ça.

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; 
} 

et comme une amélioration plus loin, vous pouvez fournir des valeurs par défaut lorsque l'appelant n'a pas spécifié toutes les clés attendues

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

... et si vous voulez être résistant contre les fautes de frappe, vous pouvez 'supprimer $ args {$ key} 'chaque argument afin que vous puissiez ensuite vérifier les arguments inutilisés comme' if (mon @unknown = trier les clés% args) {croak "Unknown named arguments: @unknown"; } ' – amon

+0

J'ai essayé les deux solutions et les deux ont fonctionné parfaitement. – ahmedus

+0

'my $ self = {@_}' rompt l'abstraction. Je pense que vous devriez le marquer comme étant indésirable au moins. – Borodin