CIT 042 Index > Object-Oriented Perl

Object-Oriented Perl

This page is written using terminology that should be familiar to people who use Java.

Creating an Object

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.

Object Methods

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 blessed the $worker, and pass the object reference as the first parameter. This notation is easier to write than Employee::set_name($worker, "Fred Flintstone").

A Better Way to do Get/Set

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

A Better Way to do 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
);

Inheritance

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-blesses 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";