1 Object-oriented programming in Perl
In the following example, a package (or class) Student is defined.
It contains three methods: new(), printDetails() and enroll().
The method new() is used as a constructor to instantiate new objects.
But it is just a convention to use the word "new", any other word
could be used instead.
The objects of the class Student have two attributes: name and courses.
These are numbered $_[1] and $_[2] in the subroutine because the
name of the package itself is stored in $_[0].
#!/usr/local/bin/perl
#########################################
package Student;
sub new {
my $self = {};
bless $self;
$self->{name} = $_[1];
$self->{courses} = $_[2];
return $self;
}
sub printDetails {
my $self = $_[0];
print "Name: $self->{name}\n";
print "Courses: @{$self->{courses}}\n";
}
sub enroll {
my $self = $_[0];
my $course = $_[1];
push (@{$self->{courses}},$course);
}
#########################################
package main;
my($student1) = new Student("Fred", ["L548"]);
print "Input the courses which $student1->{name} is enrolled in.\n";
print "When finished, type X.\n";
$newcourse = <STDIN>;
chomp $newcourse;
while ($newcourse !~ /x/i) {
$student1->enroll($newcourse);
$newcourse = <STDIN>;
chomp $newcourse;
}
$student1->printDetails();
1.2 Exercises
1) Add further attributes to the student class (phone number, email address,
degree, etc).
2) Create an array of students. Let users add new students to the array.
Ask the user for the name of a student and then print his/her details.
3) Create a method creditHours that computes the number of credit hours
for a student
assuming that every class is a three credit class.
4) Create a class Employee that contains information
about names, ages and positions. What could be useful methods
for the class?
1.2 Blessing of $self
Without blessing the variable in the subroutine "new",
a different notation would have to be used:
Student::printDetails($student1);
instead of
$student1->printDetails();
Using that notation any subroutine from any package can be included in
a script. A blessed variable
contains an internal pointer to its package, i.e. the variable
becomes an "object" of that class.
1.3 Optional Materials: Pointers (References)
The following examples provide more details for the notation (implementation)
of object-oriented programming in Perl. Object-oriented notation was added
to Perl in version 5. Therefore existing constructs (such as pointers
and hashs) were used for the object-oriented features.
#!/usr/local/bin/perl
# normal hash
%hash = ("name", "Fred", "color", "white");
print "$hash{name}\n";
print "$hash{color}\n";
# pointer to a hash
$pointer_to_hash = \%hash;
print "$pointer_to_hash->{name}\n";
print "$pointer_to_hash->{color}\n";
The subroutine "new" returns a pointer to a hash.
The hash is defined as "$self = {...}" instead of as "%self =(...)".
"$self" is a scalar and therefore a pointer to a hash.
#!/usr/local/bin/perl
sub new {
my $self = {};
$self->{'name'} = $_[0];
$self->{'color'} = $_[1];
return $self;
}
my($cat) = new("Fred","white");
print "$cat->{name}\n";
print "$cat->{color}\n";
1.4 Another example
#!/usr/local/bin/perl
package Cat;
sub new {
my $class = $_[0];
my $self = {};
bless $self;
$self->{'name'} = $_[1];
$self->{'color'} = $_[2];
return $self;
}
sub meow {
print "meow\n";
}
sub printDetails {
my $self = $_[0];
print "$self->{name}\n";
print "$self->{color}\n";
}
###################################
package main;
my($cat) = new Cat("Fred", "white");
$cat->meow();
$cat->printDetails();
- object or instance: $cat
- class: Cat
- attribute: name, color
- behaviour or methods: new(), meow(), printDetails()
- constructor method: new()
- instance method: printDetails()
- class method: meow()
1.5 Exercise
5) In analogy to the example above, create a package (class) for another
type of pet besides cat or dog (see below).
1.6 Encapsulation, inheritance, and polymorphism
#!/usr/local/bin/perl
package Animal;
sub printDetails {
my $self = $_[0];
print "$self->{name}\n";
print "$self->{color}\n";
}
###################################
package Cat;
@ISA = qw(Animal);
sub new {
my $class = $_[0];
my $self = {};
bless $self;
$self->{'name'} = $_[1];
$self->{'color'} = $_[2];
return $self;
}
sub speak {
print "meow\n";
}
###################################
package Dog;
@ISA = qw(Animal);
sub new {
my $class = $_[0];
my $self = {};
bless $self;
$self->{'name'} = $_[1];
$self->{'color'} = $_[2];
return $self;
}
sub speak {
print "woof\n";
}
###################################
package main;
my($cat) = new Cat("Fred", "white");
my($dog) = new Dog("Max", "black");
@pets = ($cat,$dog);
foreach $pet (@pets){
$pet->speak();
$pet->printDetails();
}
- encapsulation: the implementation of printDetails() is hidden from
Cat and Dog
- inheritance: Cat and Dog inherit printDetails()
- polymorphism: $pet refers to instances of different types()
1.7 Exercise
6) Add your pet from the previous exercise to the Animal package.
1.8 Modules
A module is a package stored in a file by itself and named
"packagename.pm". The last executed line in a module should be
"return 1;". A package can be used in a different file by including
"use packagename;" at the beginning of the file.
1.9 Exercise
7) Save Animal, Cat, Dog and the additional pet
as modules by themselves. To use them you can
either include "use" statements for all four of them in the main file
or you use Cat, Dog and the other pet in the main file and Animal
in Cat, Dog and the other pet.
Try both possibilities.