5.6 Object-Oriented Programming
In order to write object-oriented programs in Perl, we need to use the concepts of references and packages. Unlike most other languages, Perl does not provide much additional syntax for creating and manipulating objects.
First, let us briefly discuss some basic concepts regarding object-oriented programming in general. To write object-oriented programs in a certain domain of interest, we need to identify classes of objects in the domain. Sometimes, we can represent the set of classes using a hierarchy. Sometimes, a hierarchy is not enough. A network is needed for representation if there are classes that have more than one ancestor class. In the example we discuss in this section, we have a simple hierarchy where each subclass has only one parent class. Therefore, the set of classes in our example can be organized as a tree.
A class that does not have any ancestor is called the root class. A class may have descendants. Direct descendants are called subclasses or children of the class; the original class then is also called the parent class or the direct superclass. An example of a class is one we can name Person that stores information about a person in general. We can create children classes of Person such as Friend, Acquaintance and Enemy. These three classes may have children classes of their own.
A class or subclass at any level may have instances. An instance is a specific example of an individual belonging to that class. For example, we can have instances named $erin and $ron of the class called Person, and instances such as $tommy and $jeff of the subclass Friend.
The reason for organizing classes in a hierarchy is to be able to store information about a related set of classes and instances in an efficient manner. This efficiency is achieved due to the use of inheritance. A descendant class inherits information from its ancestor classes. A property that is associated with a class is inherited by all descendant classes. For example, if we assume that the class Person has a property called name, the children classes Friend,
Acquaintance and Enemy all will have the same property name. Usually, object-oriented programming languages allow two types of inheritance:
• inheritance of simple properties or slots or fields; these may be scalars or more complex data structures, and
• inheritance of subroutines that perform useful tasks for the subclass as well as the ancestors.
Subroutines that are defined inside a class definition are usually called methods in object-oriented terminology. In Perl, inheritance is performed by using the @ISA list variable in each package where a class is defined. Below we see how this is done.
In the program given below, we first define two classes: Person and Friend. In Perl, we define a class by defining a package of the same name. All information regarding the class must be stated inside this package. Person is the root class, and Friend is its subclass. We do not define the classes Acquaintance and Enemy to keep the program short. The
definition of the class Person is contained in the package Person and the definition of the class Friend is contained in the package named Friend. The class Friend is a direct child class of the class Person.
Finally, in the program, we have the package main. In this package, we define two instances of the class Person and two instances of the class Friend. Then, we print the information contained in these four instance objects. When we print the contents of the instances of the child class Friend, we note that it inherits two methods set_name and get_name from the parent class Person. We also note that Perl allows inheritance of methods only. It does not allow inheritance of simple fields like most other programming languages do. Inheritance of simple
properties of a class must be simulated using inheritance of subroutine-based properties or methods. We see how this is done in the example program that follows.
Program 5.16
#!/usr/bin/perl
package Person;
#If we write `use strict' here, we will have problems because the @ISA
#variable in a package cannot be declared with `my'. We can write
#`use strict' in package Person if it was put in a module Person.pm by itself.
sub make{ #A method to create an instance of class Person
my ($self, $class);
$self ={}; #Initialize $self to reference an empty hash.
$class = $_[0]; #This is the class of the instance to create
$self -> {name} = undef; #Set the `name' field to an undefined value
bless ($self, $class); #$self is `blessed' to become an instance of $class
return $self;
}
sub set_name { #A method to assign the name field
my $self = $_[0];
$self -> {name} = $_[1];
}
sub get_name{ #A method to access the name field
my $self = $_[0];
my $name = $self -> {name};
return $name;
}
#--------------------------------
package Friend;
#We will have to write `use Person' here if we had a module Person.pm where
#the definition for Person class was stored;
@ISA = ("Person"); #A `Friend' is a subclass of class `Person'
sub make { #A constructor method for class `Friend'
my $self = {}; #Class `Friend' has two fields and inherits one from
my $class = $_[0]; #parent class `Person'
$self -> {hometown} = undef; #Set the two fields to `undef'
$self -> {age} = undef;
bless ($self, $class); #Person has no parents
}
sub set_hometown {
my $self = $_[0];
$self -> {hometown} = $_[1];
}
sub get_hometown{
my $self = $_[0];
return $self -> {hometown};
}
sub set_age {
my $self = $_[0];
$self -> {age} = $_[1];
}
sub get_age{
my $self = $_[0];
return $self -> {age};
}
#-----------------------------------
package main;
#We will have to write `use Friend' here if we had a module Friend.pm where
#the definition for Person class was stored;
#Create two instances of Person, and two instances of Friend
my ($erin, $ron, $jeff, $tommy);
$erin = Person -> make; $erin -> set_name ("Erin");
$ron = Person -> make; $ron -> set_name ("Ron");
$jeff = Friend -> make; $jeff -> set_name ("Jeff");
$jeff -> set_hometown ("Boulder");
$jeff -> set_age (21);
$tommy = Friend -> make; $tommy -> set_name ("Tommy");
$tommy -> set_hometown ("Washington DC");
$tommy -> set_age (18);
#Print information contained in the object instances
printf "%-7s\n", $ron -> get_name;
printf "%-7s\n", $erin -> get_name;
printf "%-7s%-15s%d\n", $jeff -> get_name,
$jeff -> get_hometown, $jeff -> get_age;
printf "%-7s%-15s%d\n", $tommy -> get_name,
$tommy -> get_hometown, $tommy -> get_age;
The output of running this program is given below.
Ron Erin Jeff Boulder 21 Tommy Washington DC 18