Objects in Perl

Why Objects

Objects make programming easier.  We use objects to hide complex functions and data types from the use of the function.

For example, suppose you want to have an interface between your program and some database.  This interface could take thousands of lines of code, and be very complex internally.  However, it need not look complex to the user of the interface.  Instead he is just given a few simple calls like connect, fetch_array, etc.

Perl has many such packages available for use.  Much of the power of Perl is within these packages.

The Fraction Class

Here we will explore a very simple package; one that implements simple fractions like 5/3 or 2/7.  It stores the fraction as two numbers, a top and a bottom.  The package can make a new fraction, set the value of a fraction, add to fractions together, and print a fraction.

The program that uses the fraction package is simple, and easy to read.  You can find the source code to the main program and to the fraction class.
 

#!/usr/bin/perl -w

use Fraction;

$f1 = Fraction->new();
$f2 = Fraction->new();

$f1->set(5, 3);
$f2->set(2,5);
print "The fraction " . $f1->toString() . " + " . $f2->toString();
$f1->add($f2);
print " is " . $f1->toString() . "\n";


 

Start a new class

Make a name for this object.  I'll call it 'Fraction'.   Make a file named 'Fraction.pm'.  The first line of the file should say
package Fraction;
This declares that all of the code in this file will use the namespace Fraction.  A namespace is a set of code that call all access the same variables, and that code using those variable names but not within the namespace cannot use the variables.  In this case, it means that  any variable like $age can be used within this file, but will not be effected by any code outside the file.  Namespaces keeps this object's code from effecting the variables of other code.

Write the New function

An object in perl is really a hash of variables, all assigned to a namespace.  The new function is responsible for contructing the new hash, and assigning to the namespace.  It will be given as it's one parameter the name of the class.  Within the new function, you will use the 'bless' command.  Bless takes two arguments: the  has, and the namespace.  Bless is somewhat like the cast function in C/C++/Java.

The new function should return the hash/array you just made.  Having the bless function as the last line of the new function causes the return value of bless to be returned by new, which also works.

sub new {
    my($class) = shift;
    bless {
        "top" => 0,
        "bot" => 0
    }, $class;
}

The operator => is really just a comma, but the Perl object people like to use =>.  The bless line could also be written
bless( {"top", 0, "bot", 0}, $class);
which makes it more clear that the first argument is just a hash (associative array) and the second the name of a namespace.

Write More Functions

Given an object, we need functions to manipulate the object.  Normally, every function for the object goes in the same file.  However, the actual rule is that each function must be written in a file starting package Fraction,  and that file must have been use'd by the calling file.  It easiest just to do it all in the same file, however.

Every function is automatically given as the first parameter a reference to the hash.  Normally we call that $self.
sub set {
    my($self) = shift;
    my($newtop) = shift;
    my($newbottom) = shift;

    $self->{"top"} = $newtop;
    $self->{"bot"} = $newbottom;
}

Writing even more functions

Often, you will want to access more than one member of a class from the same function.  In this example, you might want to add two Fractions together.  Generally, one of them will be self and the other will be passes as an argument to the function.  For example ...
sub add {
   my($self) = shift;
   my($f2) = shift;
   my($top) = $self->{"top"};
   my($otop) = $f2->{"top"};
   my($bot) = $self->{"bot"};
   my($obot) = $f2->{"bot"};
   $self->set($top*$obot + $otop * $bot, $bot * $obot);
}

Finishing the Object

Here are to little tricks.  It's generally a good idea to have a function named toString, that takes no arguments (except self, of course) and returns a string describing the object.  This function is very useful for debugging, and you will generally fund other uses also.
sub toString {
   my($self) = shift;
   my($top) = $self->{"top"};
   my($bot) = $self->{"bot"};
   return "$top / $bot";
}
Also, Perl requires that every file you will use return true if it successfully loads.  Therefore, every file defining an object should have as it's last line 
1;
That strange line tells the file that loaded the object that the object was loaded successfully.

Using Objects

Given you have an object, it's important