.1. In Perl, the constructor is just a subroutine called new.
Yes, by convention new
is a constructor. It may also perform initialization or not. new
should return an object on success or undefined if an error has occurred that prevents object creation.
You can name your constructor anything you like, have as many constructors as you like, and even build bless objects into any name space you desire.
.2. I don't get what my $type = shift;
does at all, but I always see it. Do I need it?
shift
with no arguments takes an argument off the head of @_
and assigns it to $type
. The ->
operator passes the invocant (left hand side) as the first argument to the subroutine. So this line gets the class name from the argument list. And, yes, you do need it.
.3. How does an array of inputs become the %params
hash? my %params = @_;
Assignment into a hash is done in list context, with pairs of list items being grouped into as key/value pairs. So %foo = 1, 2, 3, 4;
, creates a hash such that $foo{1} == 2
and $foo{3} == 4
. This is typically done to create named parameters for a subroutine. If the sub is passed an odd number of arguments, an warning will be generated if warnings are enabled.
.4. What does 'my $self = {};` do?
This line creates an anonymous hash reference and assigns it to the lexically scoped variable $self
. The hash reference will store the data for the object. Typically, the keys in the hash have a one-to-one mapping to the object attributes. So if class Foo has attributes 'size' and 'color', if you inspect the contents of a Foo object, you will see something like $foo = { size => 'm', color => 'black' };
.
.5. Given $self->{'High'} = $params{'High'};
where does $params{'High'}
come from?
This code relies on the arguments passed to new
. If new
was called like Foo->new( High => 46 )
, then the hash created as per question 3 will have a value for the key High
(46). In this case it is equivalent to saying $self->{High} = 46
. But if the method is called like Foo->new()
then no value will be available, and we have $self->{High} = undef
.
.6. What does bless
do?
bless
takes a reference and associates with a particular package, so that you can use it to make method calls. With one argument, the reference is assoicated with the current package. With two arguments, the second argument specifies the package to associate the reference with. It is best to always use the two argument form, so that your constructors can be inherited by a sub class and still function properly.
Finally, I'll rewrite your hash based object accessor as I would write it using classical OO Perl.
package Foo;
use strict;
use warnings;
use Carp qw(croak);
sub new {
my $class = shift;
croak "Illegal parameter list has odd number of values"
if @_ % 2;
my %params = @_;
my $self = {};
bless $self, $class;
# This could be abstracted out into a method call if you
# expect to need to override this check.
for my $required (qw{ name rank serial_number });
croak "Required parameter '$required' not passed to '$class' constructor"
unless exists $params{$required};
}
# initialize all attributes by passing arguments to accessor methods.
for my $attrib ( keys %params ) {
croak "Invalid parameter '$attrib' passed to '$class' constructor"
unless $self->can( $attrib );
$self->$attrib( $params{$attrib} );
}
return $self;
}