This page is written using terminology that should be familiar to people who use Java.
bless
ed
reference to some entity in the package.Let’s say we want an Employee
object with properties name
, id
,
and age
. We will name our package
Employee
and begin it this way:
#!/usr/bin/perl package Employee; sub new { my $class = shift; print "Creating new $class\n"; my $self = { }; bless $self; $self->{"name"} = ""; $self->{"id"} = ""; $self->{"age"} = 0; return $self; } 1;
The lines in boldface are the important ones here;
the first line creates an anonymous hash reference,
and the bless
line “marks”
that object as having been created by the Employee
package.
We can create an object in our main program by saying this:
#!/usr/bin/perl use Employee; $worker = Employee->new();
When you use a package name with pointer notation
(the ->
), you are calling a class
method (in Java, a static method). You are saying,
“call the new
subroutine in the
Employee
package, and pass the name
of the package as the first parameter. This
notation is easier to write than
Employee::new("Employee")
.
Now $worker
contains a reference
to that anonymous hash that was created in the
new
subroutine.
This worker has only a null string for name and ID, and an age of zero. The next step is to write methods that will set these values, and other methods that will retrieve the values (this is done in the Java methodology):
sub set_name { my $self = shift; my $value = shift; $self->{"name"} = $value; } sub get_name { my $self = shift; return $self->{"name"}; }
And we call them from the main program this way:
$worker->set_name("Fred Flintstone"); $test = $worker->get_name(); print "Worker is named $test\n";
When you use an object reference with pointer notation
(the ->
), you are calling an instance
method. You are saying,
“call the set_name
or
get_name
subroutine in the
Employee
package (since that is who has
bless
ed the $worker
,
and pass the object reference as the first
parameter. This
notation is easier to write than
Employee::set_name($worker, "Fred Flintstone")
.
In Java, you must use separate methods for setting and getting object properties, because a method can’t take a variable number of parameters. However, you can give a variable number of parameters in Perl, so it’s the custom to have one method that will both set and get a property, depending upon how it is called:
sub name { my $self = shift; if (scalar(@_) == 1) { $self->{"name"} = shift; } return $self->{"name"}; }
And the main program is changed to this:
$worker->name("Fred Flintstone"); $test = $worker->name(); print "Worker is named $test\n";
new
Similarly, you could have a new
function that expects its parameters in order of
name, id, and age:
# in the package sub new { my $class = shift; my $self = { }; bless $self; $self->{"name"} = shift; $self->{"id"} = shift; $self->{"age"} = shift; return $self; }
# in main program $worker = Employee->new("Fred Flintstone", 1234, 40);
Or, you could have the user set the hash herself, which would let her put the parameters in any order she found to be convenient:
# in the package sub new { my $class = shift; my $self = {@_ }; bless $self; return $self; }
# in main program $worker = Employee->new( "name" => "Fred Flintstone", "id" => 1234, "age" => 40 );
Remember that @ISA
array that we
declared at the beginning of modules that used
the exporter? That stands for “is
a”—it means that our module is a(n)
exporter. That’s how you do inheritance with
object-oriented Perl. Let’s create a
Salaried
class, that adds a monthly
salary as a property and an annual_wage()
method:
#!/usr/bin/perl package Salaried; @ISA = qw(Employee); sub new { my $class = shift; my $self = Employee->new(@_); bless $self, $class; return $self; } sub annual_wage { my $self = shift; return $self->{"salary"} * 12; } 1;
Notice what the new
subroutine does.
First it creates an Employee
, so that it
can call its new
subroutine.
Then it re-bless
es itself to become a
Salaried
object. We can then write
our main program as follows. Note that, because
we are passing all the object’s properties in
the parameter list, we just add the salary along with
all the rest.
use Employee; use Salaried; $worker = Salaried->new( "name"=>"Fred Flintstone", "id" => 1234, "age"=>40, "salary" => 3000 ); $test = $worker->name(); $amount = $worker->annual_wage(); print "Worker $test earns $amount dollars per year\n";