user3885596
user3885596

Reputation:

How to initialize a specific class variable while creating an object?

So far I always relied on the order of variables in a class, but now I'm trying to initialize those variables in a shuffled order.

For example, this is what I normally do while creating an object.

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

And this is what I'm trying to achieve.

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

I tried => regarding to several documents (e.g. perldoc) I saw, but they didn't return a complete example to me. However I don't actually work on the following script, it's a fair MCVE with the 'cliché' package 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, '', '');

The output is as follows.

First name : Fernando
Last name  : Alonso
Age        : 36

First name : Age
Last name  : 36
Age        : 

So, how should I create the object to make explicit assignments to the class variables? If necessary, how should I modify package Person?

P.S. I avoid changing the variables after the object is created.

Upvotes: 1

Views: 175

Answers (1)

mob
mob

Reputation: 118605

The original Person class constructor expects the arguments to contain values in a specific order, but you want to specify key-value pairs. This is easy enough by representing the input as a hash reference.

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

If you want to restrict the keys that can be set to FirstName, LastName, and Age, you could do something like this.

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

and as a further enhancement, you could provide default values where the caller has not specified all of the expected keys

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

Upvotes: 4

Related Questions