Chapter 7 Object oriented Perl programming - People

handprintSoftware and s/w Development

Nov 18, 2013 (4 years and 1 month ago)

92 views

Chapter 7
Object oriented Perl programming
7.1 Introduction to chapter 7
The purpose of this chapter is to give a brief introduction to object oriented Perl program-
ming so let's get to it.What are objects?Objects are like little machines of code.They
contain functions and data.Often the functions are used to mangle the data.Like a house-
hold blender.You ll it with tomatoes,premium Swedish vodka,and spicy Tabasco (the
data).Then you call the blend function and voila you have your self a nice Bloody Mary.
Before we can go into the juicy details of objects,we need to go through some things about
references and packages.
7.2 References in Perl
There are three main data types in Perl,scalars,arrays and hashes.References in Perl are
like pointers to the data of a certain type (technically references are also scalars but this is
not something we need to care about for the moment).Lets look at an example where we
make three variables,one of each data type,and then make references to them.
refs.pl
1
#!/usr/bin/perl -w
2
use strict;
3
#short recapitulating what references are
4
5
#data types
6
my $scalar ="This is a scalar";
7
my @array = ("Zero","One","Two");
8
my %hash = ("Marge"=>"Homer","Hillary"=>"Bill");
9
10
#references to them
11
12
my $scalar_r =\$scalar;
13
my $array_r =\@array;
14
my $hash_r =\%hash;
15
16
#dereferencing using the arrow notation
140
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 141
17
18
print $$scalar_r,"\n";
19
20
print $array_r->[0],"\n";
21
print $array_r->[1],"\n";
22
print $array_r->[2],"\n";
23
24
print $hash_r->{"Marge"},"\n";
25
print $hash_r->{"Hillary"},"\n";
refs.pl
Running this program gives the following result:
refs.out
1
This is a scalar
2
Zero
3
One
4
Two
5
Homer
6
Bill
refs.out
The syntax for using references is almost the same as with ordinary variables except that
for scalars you need to add an extra $ before using the variable.For arrays and hashes
the syntax is also similar but you have to use an extra arrow (->) for dereferencing.One
thing about references that can not be stressed enough is the following:IF YOU MODIFY
DATA BY A REFERENCE IT WILL CHANGE THE DATA EVERYWHERE!Now before
reading on,go do follow up task 1.
7.2.1 Anonymous references and more dereferencing
Programming would be complicated if we had to create a variable each time before we could
make a reference to it.Thus the Perl gurus have blessed us with the concept of anonymous
references.This is how they work.
anonymousRefs.pl
1
#!/usr/bin/perl -w
2
use strict;
3
4
#anonymous references are created like this
5
my $scalar_ref;#nobody in their right mind would do this!
6
my $aref = [1,2,3];
7
my $href = {'Marge'=>'Homer','Hillary'=>'Bill'};
8
9
#using an array ref like an array
10
foreach my $number ( @{$aref} ){
11
print"$number\n";
12
}
13
14
#using a hash ref like a hash
15
foreach my $key ( keys %{$href} ){
16
print"key:$key\n";
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 142
17
print"value:",$href->{$key},"\n";
18
}
anonymousRefs.pl
This example also shows how to use a reference in the same way that you normally use
arrays and hashes.The output of the program is this
anonymousRefs.out
1
1
2
2
3
3
4
key:Marge
5
value:Homer
6
key:Hillary
7
value:Bill
anonymousRefs.out
7.2.2 Building complex data structures with hash references
In case your wondering what a complex data structure is,heres an example:Imagine an
array whose rst element is a reference to a hash that has a key"le cle"whose value is
a reference to an array whose rst element is the string"are you confused yet?"and
whose second element is a reference to the array that we started out with.Hashes or hash
references are good for building arbitrarily complex data structures.This is because the
value of a hash key can be a reference to anything else.Just imagine how complicated this
can get.Let's start out with a simple example and walk though it line by line.
hashRefsBuildingFromVariables.pl
1
#!/usr/bin/perl -w
2
use strict;
3
4
my $hr;
5
6
#buidling hashrefs from data
7
my $scalar ="A string";
8
my @array = ("Thing one","Thing two");
9
my %hash = ("Marge"=>"Homer","Monica"=>"Bill");
10
11
$hr->{"scalar"} =\$scalar;
12
$hr->{"array"} =\@array;
13
$hr->{"hash"} =\%hash;
14
15
print $hr->{"scalar"},"\n";
16
print $hr->{"array"}->[0],"\n";
17
print $hr->{"array"}->[1],"\n";
18
19
print $hr->{"hash"}->{"Marge"},"\n";
hashRefsBuildingFromVariables.pl
You may need to read these sentences many times before you get the hang of what's going
on.$hr is a reference to a hash.This hash has a key called"scalar",and the value of
this key is a reference to a scalar,containing the string"A string".It also has a key called
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 143
"array"and the value of this key is a reference to an array.The key called"hash"has a
value that is a reference to a hash.Watch carefully how to dereference the rst element of
the array pointed to by the value of the key"array"of the hash pointed to by $hr (line
16).Also observe how to dereference the value of the key"Marge"of the hash pointed to
by the value of the key"hash"of the hash pointed to by $hr (line 19).The sentences are
complicated,and this re ects the level of complexity of the data structure.At this stage
you will perhaps start appreciating the array (->) notation which graphically depicts these
relations.The output of the program is given below:
hashRefsBuildingFromVariables.out
1
SCALAR(0x7be370)
2
Thing one
3
Thing two
4
Homer
hashRefsBuildingFromVariables.out
As you can see the rst line of the output does not contain what one would expect.This is be-
cause we are trying to print a reference to a scalar,not the scalar pointed to by the reference.
When you run the example,change the print statement on line 15 to ${$hr->{"scalar"}}.
Also compare this notation to the one used in anonymousRefs.pl.Now go do follow up task
2.Finished?Good,let's take a look at the following example where we create the a similar
data structure.
arrayRefsBuildingFromVariables.pl
1
#!/usr/bin/perl -w
2
use strict;
3
4
my $hr;
5
6
#buidling arrayrefs from data
7
my $scalar ="A string";
8
my @array = ("Thing one","Thing two");
9
my %hash = ("Marge"=>"Homer","Monica"=>"Bill");
10
11
$hr->[0] =\$scalar;
12
$hr->[1] =\@array;
13
$hr->[2] =\%hash;
14
15
print $hr->[0],"\n";
16
print $hr->[1]->[0],"\n";
17
print $hr->[1]->[1],"\n";
18
19
print $hr->[2]->{"Marge"},"\n";
arrayRefsBuildingFromVariables.pl
The only dierence this time is that we've made $hr into an array instead of a hash.This
piece of code will produce the same output as the hashRefsBuildingFromVariables.pl exam-
ple.To convince yourselves take a look at the output.
arrayRefsBuildingFromVariables.out
1
SCALAR(0x7be370)
2
Thing one
3
Thing two
4
Homer
arrayRefsBuildingFromVariables.out
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 144
The output is exactly the same.But it didn't have to be.Why?Remember that a refer-
ence in nothing but a scalar whose value is the memory address where the string is stored.
Thus,the rst entry might change because the memory location where the string is stored
will probably be dierent between runs.The reason for this lies deep within the memory
management of our operating system and is way beyond the scope of this course.
As the key to learning anything is repetition here is the same (almost) example again,this
time using an anonymous array and an anonymous hash.Can you see why this example
prints right?Try before you look at the footnote
1
hashRefsBuildingAnonymously.pl
1
#!/usr/bin/perl -w
2
use strict;
3
4
my $hr;
5
6
$hr->{"scalar"}="A string";
7
$hr->{"array"}=["Thing one","Thing two"];
8
$hr->{"hash"}={"Marge"=>"Homer","Monica"=>"Bill"};
9
10
print $hr->{"scalar"},"\n";
11
print $hr->{"array"}->[0],"\n";
12
print $hr->{"array"}->[1],"\n";
13
14
print $hr->{"hash"}->{"Marge"},"\n";
hashRefsBuildingAnonymously.pl
hashRefsBuildingAnonymously.out
1
A string
2
Thing one
3
Thing two
4
Homer
hashRefsBuildingAnonymously.out
Since the most important thing to remember about references is that IF YOU MODIFY
DATA BY A REFERENCE IT WILL CHANGE THE DATA EVERYWHERE,you might
wonder how to make a copy of the data pointed to by a reference.The example below shows
a technique for this:
hashRefsExtracting.pl
1
#!/usr/bin/perl -w
2
use strict;
3
4
my $hr;
5
6
#extracting the data from hashrefs
7
$hr->{"scalar"}="A string";
8
$hr->{"array"}=["Thing one","Thing two"];
9
$hr->{"hash"}={"Marge"=>"Homer","Monica"=>"Bill"};
10
1
Because here the value of the key"scalar"of the hash pointed to by the hash reference $hr is a scalar,
and not a reference to a scalar
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 145
11
my %hash_copy = %{$hr->{"hash"}};
12
my @array_copy = @{$hr->{"array"}};
13
14
$array_copy[0]="Thing one modified?";
15
16
print $hr->{"array"}->[0],"\n";
17
18
19
20
hashRefsExtracting.pl
hashRefsExtracting.out
1
Thing one
hashRefsExtracting.out
As you can see in the output,modifying the copy (line 14) will not modify the anonymous
array pointed to by the value of the key"array"of the hash pointed to by $hr.In this
example the %{...} and @{...} notations are used which means that the assignments at
line 11 and 12 work like normal assignments,i.e.copies.It exactly the same as if you type
@a=@b;then @a will be a copy of @b and similarly for hashes.
Now pay careful attention to the following example:
hashRefsModifying.pl
1
#!/usr/bin/perl -w
2
use strict;
3
4
my $hr;
5
6
#modifying the data in hashrefs
7
$hr->{"scalar"}="A string";
8
$hr->{"array"}=["Thing one","Thing two"];
9
$hr->{"hash"}={"Marge"=>"Homer","Monica"=>"Bill"};
10
11
$hr->{"array"}->[0]="Thing one modified!";
12
print $hr->{"array"}->[0],"\n";
13
14
my $array_ref_from_hr = $hr->{"array"};
15
$array_ref_from_hr->[0]="Thing one modified again!";
16
print $hr->{"array"}->[0],"\n";
hashRefsModifying.pl
hashRefsModifying.out
1
Thing one modified!
2
Thing one modified again!
hashRefsModifying.out
On line 11 we simply modify the rst element of the array pointed to by the value of the
key"array"of the hash pointed to by $hr.On line 14 we copy the reference to the array
pointed to by the value of the key"array"of the hash pointed to by $hr.Then,on line 15
we modify the rst element of the array pointed to by the reference $array
ref
from
hr.
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 146
This reference points to the same data as is pointed to by the value of the key"array"of
the hash pointed to by $hr.Thus the result.
That was just the warmup but don't break down just yet.There is a light in the tunnel.The
following example shows a complex data structure that is supposed to represent a decision
tree facing us when we leave this lecture room.If I go to the left there is a coee machine.
If I have money I will get drinks and if I have no money I will get thirst.If I go to the right
I will nd the library.Depending on my mood for the day,various selections of books are
available.
hashRefsComplex.pl
1
#!/usr/bin/perl -w
2
use strict;
3
use Data::Dumper;
4
my $hr;
5
6
my $drinks = ['cappuccino','espresso','chocolate'];
7
my $thirst = ['thirst'];
8
my $slack_book = ['Kicking back for dummies'];
9
my $serious_books = ['Camel book','Panther book','Algorithm theory'];
10
11
$hr->{'left'}->{'coffeemachine'}->{'money'}=$drinks;
12
$hr->{'left'}->{'coffeemachine'}->{'nomoney'}=$thirst;
13
$hr->{'right'}->{'library'}->{'serious'}=$serious_books;
14
$hr->{'right'}->{'library'}->{'slacker'}=$slack_book;
15
16
print Dumper($hr);
hashRefsComplex.pl
Since the code is much clearer than my wording I will leave it uncommented.What is new
in this example is the level of depth of references and that might seem depressing.But by
using a nifty little module called Data::Dumper we can get a very clear representation of the
data structure we are dealing with.Look at the output.
hashRefsComplex.out
1
$VAR1 = {
2
'left'=> {
3
'coffeemachine'=> {
4
'nomoney'=> [
5
'thirst'
6
],
7
'money'=> [
8
'cappuccino',
9
'espresso',
10
'chocolate'
11
]
12
}
13
},
14
'right'=> {
15
'library'=> {
16
'slacker'=> [
17
'Kicking back for dummies'
18
],
19
'serious'=> [
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 147
20
'Camel book',
21
'Panther book',
22
'Algorithm theory'
23
]
24
}
25
}
26
};
hashRefsComplex.out
Now you may do follow up task 3.If you feel that you want to know more about references
type man perlreftut or man perlref in your terminal.
7.2.3 Follow up tasks
1.Modify refs.pl to print the keys and values of the hash,using the $hash variable.
Then change the value of one of the hash keys by using the hash reference $hash
r.
Then print keys and values again using the $hash variable.
2.Modify hashRefsBuildingAnonymously.pl to print the elements of the array
pointed to by $hr->{"array"} using a foreach loop using the following syntax:
@{$hr->{"array"}}.Similarly print the keys and values of the hash.
3.Use Data::Dumper in some of the previous examples to dump out the data structure.
7.3 Packages in Perl
There are many aspects of packages in Perl.Most modules,for instance,are dened in one
or more packages.The way we will use packages here is just as a wrapper for function names;
what is sometimes called a namespace.The rationale is that if you write an awful lot of
functions you do not want to look out for name clashes { and there are myriads of functions
written in Perl.Lets go ahead and dene a package:
Wrapit.pm
1
package Wrapit;
2
use strict;
3
4
#Wrapit is just a namespace.Good for hiding functions
5
6
sub args {
7
my $ret ="I got".join('',@_);
8
return $ret;
9
}
10
11
1;
Wrapit.pm
Note that the name of the le containing the package is the same as the package's name.
This is the convention in Perl.Here is an example of how to use Wrapit.
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 148
useWrapit.pl
1
#!/usr/bin/perl -w
2
use Wrapit;
3
4
#Three ways of calling subroutine args in package wrapit
5
$args1 = Wrapit->args("Hello!");
6
$args2 = args Wrapit ("Hello!");
7
$args3 = Wrapit::args("Hello!");
8
9
print"First way:\t $args1\n";
10
print"Second way:\t $args2\n";
11
print"Third way:\t $args3\n";
useWrapit.pl
Line 2 states that we will use Wrapit.It is important that there is a le called Wrapit.pm
in the directory where the calling Perl script is in.If you want to nd out how to keep it
somewhere else I suggest you read man perlfaq8,look for the question\How do I keep my
own module/library directory?".To call the function name in the package we again use the
arrow operator.This is about all we need to know before starting with objects.More about
packages can be found in man perlmod.
useWrapit.out
1
First way:I got Wrapit Hello!
2
Second way:I got Wrapit Hello!
3
Third way:I got Hello!
useWrapit.out
Note that we use three distinct ways of calling our subroutine args.The rst two prepends
the package name to the rest of the arguments meanwhile the last one does not.When we
go through the syntax for object creation we will use the rst way of calling our subroutines.
I suggest you stick to that convention.
7.4 Objects in Perl
Perl objects are nothing but references (most often hash references) that know in which
package to look in for the functions to mangle their data.Here is your rst Perl class,the
code you use to dene your objects.
FirstObject.pm
1
package FirstObject;
2
use strict;
3
4
sub new {
5
my $class =shift;
6
my $self = {};
7
bless($self,$class);
8
$self->{"name"}="My name is FirstObject";
9
return $self;
10
}
11
12
1;
FirstObject.pm
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 149
There is only one function here,the constructor new.In Perl it doesn't matter what you
call the constructor,only what the constructor does.However,in case you aren't particular
about calling your constructors"honeybunny"I suggest you stick with this convention.
The rst argument that the constructor gets when you call it (more about this shortly) is
the package name,in this case FirstObject.After having shifted this name of @
,the
constructor creates a reference to an empty hash.This reference is the almost the object.
Next,the reference is told what package to look in for function calls.This is done by the
bless function;and now,the blessed reference is the object.Finally the hash pointed to
by $self is lled with some data and returned to the caller.From this point on I will drop
the\hash pointed to..."lingo,and just say object.Let's look at the caller.
useFirstObject.pl
1
#!/usr/bin/perl -w
2
use FirstObject;
3
use Data::Dumper;
4
5
my $object = FirstObject->new();
6
print $object->{"name"},"\n----------\n";
7
print Dumper($object);
8
useFirstObject.pl
Line 5 shows how to create the object and that's all there is to it.Just for the heck of it the
object is dumped by Dumper.
useFirstObject.out
1
My name is FirstObject
2
----------
3
$VAR1 = bless( {
4
'name'=>'My name is FirstObject'
5
},'FirstObject');
useFirstObject.out
7.4.1 Object attributes
Object attributes,or instance variables as they are some times referred to,is the data that
is associated with the object.Changing this data is best done by function calls,not by
operating directly on the object.The following example will illustrate this.
GetAndSet.pm
1
package GetAndSet;
2
use strict;
3
4
sub new {
5
my $class =shift;
6
my $self = {};
7
bless($self,$class);
8
return $self;
9
}
10
11
sub set_name {
12
my $self = shift;
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 150
13
my $name = shift;
14
$self->{"name"} = $name;
15
}
16
17
sub get_name {
18
my $self=shift;
19
return $self->{"name"};
20
}
21
22
1;
GetAndSet.pm
This class denes an object with only one attribute,name.By calling the function get
name
and set
name the on the object,the object changes it's name.Here's how it works:
useGetAndSet.pl
1
use GetAndSet;
2
3
my $gns = GetAndSet->new();
4
$gns->set_name("Albert");
5
print"The name of the object\$gns is:",$gns->get_name(),"\n";
useGetAndSet.pl
useGetAndSet.out
1
The name of the object $gns is:Albert
useGetAndSet.out
Now do follow up tasks 1.
An even more convenient way of changing attributes is to use the same function as both
\getter"and\setter".Like this:
GetSet.pm
1
package GetSet;
2
use strict;
3
4
sub new {
5
my $class =shift;
6
my $self = {};
7
bless($self,$class);
8
return $self;
9
}
10
11
sub name {
12
my $self = shift;
13
if(@_){
14
#if argument,set the name
15
my $name = shift;
16
$self->{"name"} = $name;
17
} else {
18
return $self->{"name"};
19
}
20
}
21
1;
GetSet.pm
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 151
I recommend this way of implementing get/set functions instead of having two separate
versions that are strictly prototyped.It saves time,both in writing and thinking.
useGetSet.pl
1
use GetSet;
2
use strict;
3
4
my $gs = GetSet->new();
5
$gs->name("Albert");
6
print"The name of the object\$gs is:",$gs->name(),"\n";
useGetSet.pl
useGetSet.out
1
The name of the object $gs is:Albert
useGetSet.out
Now let's make a slightly more complicated class.This class denes objects that have a both
a name and a list of other objects.
Person.pm
1
package Person;
2
use strict;
3
4
sub new {
5
my $class =shift;
6
my $self = {};
7
bless($self,$class);
8
return $self;
9
}
10
11
sub name {
12
my $self = shift;
13
if(@_){
14
#if argument,set the name
15
my $name = shift;
16
$self->{"name"} = $name;
17
} else {
18
return $self->{"name"};
19
}
20
}
21
22
sub friends {
23
my $self = shift;
24
if(@_){
25
foreach my $obj(@_){
26
if($obj->isa("Person")){
27
push @{$self->{"friends"}},$obj;
28
}
29
}
30
} else {
31
my $friends_array_ref = $self->{"friends"};
32
my @friends = @{$friends_array_ref};
33
return @friends;
34
}
35
}
36
1;
Person.pm
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 152
Person implements a function,friends,so that the object can hold a list of other objects.
This function checks each argument,and if it is an object of the class Person,then it is
added to the list.More about the predened isa function later.Note on line 27,how an
anonymous array is automatically created,and the objects are pushed on to it.
usePerson.pl
1
#!/usr/bin/perl -w
2
use Person;
3
use strict;
4
use Data::Dumper;
5
6
my $joey = Person->new();
7
$joey->name("Joey");
8
9
my $ross = Person->new();
10
$ross->name("Ross");
11
12
my $chandler = Person->new();
13
$chandler->name("Chandler");
14
15
$joey->friends($ross,$chandler);
16
print $joey->name(),"'s friends are:\n";
17
for my $friend ( $joey->friends() ){
18
print $friend->name();
19
print"\n";
20
}
21
22
print"--------\nNow we'll dump\$joey\n";
23
print Dumper($joey);
usePerson.pl
Note also on lines 31-33 of Person.pm that an object of this class will return a copy of the
list of friends.If Joey returned the reference to his own list of friends some evil user could
change his list to contain only Adolf Hitler,which Joey certainly wouldn't like (however in
this case the evil user could just as well change the name of some of his friends but Joey
hasn't gured that one yet).Now might be a good time for follow up task 2.
Here is the output:
usePerson.out
1
Joey's friends are:
2
Ross
3
Chandler
4
--------
5
Now we'll dump $joey
6
$VAR1 = bless( {
7
'friends'=> [
8
bless( {
9
'name'=>'Ross'
10
},'Person'),
11
bless( {
12
'name'=>'Chandler'
13
},'Person')
14
],
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 153
15
'name'=>'Joey'
16
},'Person');
usePerson.out
In so far we have let the objects (Persons) interact with each other,which is commonly
what people do.This is also true for programming;most of the time you will write classes
for objects that interact with each other and this way of programming is called composition.
However,sometimes people don't just interact but go a bit further,and this is when they
start inheriting from each other.That will be the topic for the next section.
7.4.2 Objects inheritance
There are many aspects to inheritance but for the purpose of this course we will only go
through a few of them.As usual we start with an example
Scientist.pm
1
package Scientist;
2
use Person;
3
use strict;
4
@Scientist::ISA = ("Person");
5
6
sub friends {
7
my $self = shift;
8
if(@_) {
9
foreach my $obj(@_) {
10
if($obj->isa("Scientist")) {
11
push @{$self->{"friends"}},$obj;
12
}
13
}
14
} else {
15
my $friends_array_ref = $self->{"friends"};
16
my @friends = @{$friends_array_ref};
17
return @friends;
18
}
19
}
20
21
1;
Scientist.pm
The class Scientist is a class that inherits most of its'functions from the base class Person;
after all Scientists are just people.However some scientist are picky about choosing who
they hang out with,and thus the class Scientist dees its'own friends function.Scientist
object will only hang with other scientist and thus it will check if potential friend objects
really are scientists.The other methods are inherited form the base class Person.To be
able to inherit,the Scientists class must declare its'base class,and this is done on line
4.The syntax may look a bit peculiar but this is the way it has to be if we want to use
strict.The @ISA array is an array that is automatically dened for any object of any class.
It is not an object specic attribute,but rather a class wide variable,which means that it
is the same for any object of the class.The topic of such class wide variables will not be
covered in this text.
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 154
useScientist.pl shows how the isa function is used.As you can see any derived class
object isa also an object of the base class.
useScientist.pl
1
#!/usr/bin/perl -w
2
use Scientist;
3
use Person;
4
5
my $albert = Scientist->new();
6
$albert->name("Albert");
7
if ( $albert->isa("Scientist") ) {
8
print $albert->name();
9
print"is a Scientist\n";
10
} else {
11
print $albert->name();
12
print"is NOT a Scientist\n";
13
}
14
15
if ( $albert->isa("Person") ) {
16
print $albert->name();
17
print"is a Person\n";
18
} else {
19
print $albert->name();
20
print"is NOT a Person\n";
21
}
22
23
24
my $joey = Person->new();
25
$joey->name("Joey");
26
if ( $joey->isa("Scientist") ) {
27
print $joey->name();
28
print"is a Scientist\n";
29
} else {
30
print $joey->name();
31
print"is NOT a Scientist\n";
32
}
33
34
if ( $joey->isa("Person") ) {
35
print $joey->name();
36
print"is a Person\n";
37
} else {
38
print $joey->name();
39
print"is NOT a Person\n";
40
}
41
42
43
44
45
useScientist.pl
Note how the isa function is used from within the objects when trying to get scientists like
Albert to pal up with ordinary people like Joey.Joey will be friends with anybody,as long
as they are Persons but Albert,whose friends function is overridden in the derived class
from which he is derived,will not chill with ordinary Persons.
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 155
useScientist.out
1
Albert is a Scientist
2
Albert is a Person
3
Joey is NOT a Scientist
4
Joey is a Person
useScientist.out
If this snobbish behaviour on Alberts'behalf makes you agitated,perhaps it is best that you
do follow up task 3.
7.4.3 Class documentation
Perhaps the most important issue to consider when writing code,even more important
than,IF YOU MODIFY DATA BY A REFERENCE IT WILL CHANGE THE DATA
EVERYWHERE!,is that you have proper documentation.Luckily,Perl has some very nice
documenting capabilities and even more luckily I have prepared a documentation template
for you.
ClassTemplate.pm
1
package ClassTemplate;
2
use strict;
3
4
#uncomment for inheritence
5
#@ClassTemplate::ISA = ("Parent Class");
6
7
###GENERAL DOCUMENTATION#####################################################
8
#Note that verbatim paragraphs must be preceded by a space
9
=pod
10
11
=head1 NAME
12
13
ClassTemplate - An example class with documentation
14
15
=head1 SYNOPSIS
16
17
use ClassTemplate
18
my $ct = ClassTemplate->new($arg1,$arg2)
19
my $ctname = $ct->name();
20
print my $ct;
21
22
=head1 ATTRIBUTES
23
24
name
25
Type:scalar
26
Contents:The name of the object
27
28
numbers
29
Type:Reference to array
30
Contents:Some arbitrary numbers
31
32
lookup
33
Type:Reference to hash
34
Contents:An arbitrary hash table
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 156
35
36
=head1 INHERITS
37
38
Nothing
39
40
=head1 METHODS
41
42
=cut
43
#############################################################################
44
=pod
45
46
=head2 new($name,$aref,$href)
47
48
Arguments (optional):
49
$name:the objects name
50
$aref:an array of numbers,e.g.[1,2,3]
51
$href:a reference to a hash,e.g.{'Homer'=>'Marge'}
52
Function:
53
Constructor.If arguments are given,attributes are assigned.
54
55
=cut
56
57
sub new {
58
my $class = shift;
59
my $self = {};
60
bless($self,$class);
61
if(@_==3) {#there are three args left
62
$self->name($_[0]);
63
$self->numbers($_[1]);
64
$self->lookup($_[2]);
65
}
66
return $self;
67
}
68
#############################################################################
69
=pod
70
71
=head2 name($name)
72
73
Arguments (optional):
74
$name:Scalar containig the name
75
Function:
76
If argument is given,attribute name is set.Otherwise
77
attribute name is returned
78
79
=cut
80
81
sub name {
82
my $self = shift;
83
if(@_) {#there is an argument
84
$self->{"name"}=$_[0];
85
} else {
86
return $self->{"name"};
87
}
88
}
89
#############################################################################
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 157
90
=pod
91
92
=head2 numbers($aref)
93
94
Arguments (optional):
95
$aref:Reference to array of numbers like [1,2,3]
96
Function:
97
If argument is given,attribute numbers is set.Otherwise
98
attribute numbers is returned
99
100
=cut
101
102
sub numbers {
103
my $self = shift;
104
if(@_) {#there is an argument
105
$self->{"numbers"}=$_[0];
106
} else {
107
return $self->{"numbers"}
108
}
109
}
110
#############################################################################
111
=pod
112
113
=head2 lookup($href)
114
115
Arguments (optional):
116
$href:Reference to a hash like {"Marge"=>"Homer"}
117
Function:
118
If argument is given,attribute lookup is set.Otherwise
119
attribute lookup is returned
120
121
=cut
122
123
sub lookup {
124
my $self = shift;
125
if(@_) {#there is an argument
126
$self->{"lookup"}=$_[0];
127
} else {
128
return $self->{"lookup"}
129
}
130
}
131
#############################################################################
ClassTemplate.pm
This template is a good starting point for writing new classes.Here are some short notes
about plain old documentation (pod) that are good to know.Pod is very old and thus
very fragile;but also very simple.These rules must be obeyed.Pod starts with =pod and
ends with =cut,anything between these tags is pod and not code.There may be no space
before the = sign.Headings must come on the same line as the =head[1-4] tag.Verbatim
paragraphs must be indented by a single space.Documentation is generated as follows:
pod2man ClassTemplate.pm > ClassTemplate.3
man./ClassTemplate.3#view it
pod2html ClassTemplate.pm > ClassTemplate.html
CHAPTER 7.OBJECT ORIENTED PERL PROGRAMMING 158
pod2text ClassTemplate.pm > ClassTemplate.txt
For simplicity just copy and paste the paragraphs of the template,changing names as you
see t.Now do exercise 4.Happy coding.
7.4.4 Follow up tasks
1.Change the object attribute name in useGetAndSet.pl by operating directly on the
object,i.e.treat it like a hash reference.
2.The objects of class Person don't check if a friends name is already in the list of friends.
Could you help Joey to sort this one out?
3.Make a new derived class,MovieStar that inherits from the class Person and override
the friends method.Then create Joey from the MovieStar class,some ordinary
Persons and see who Joey will hang with this time.
4.Functions in the objects of the class ClassTemplate return references to the objects'
own data.Write a program that makes an object and lls it with data using the object
functions.Then ask the object to return some of its data,i.e.attributes.Change
these attributes by reference and use Data::Dumper to dump out the object.Note
that IF YOU MODIFY DATA BY A REFERENCE IT WILL CHANGE THE DATA
EVERYWHERE.Finally rewrite the class ClassTemplate so that objects return copies
of its data and not references to it.