Chapter 8. Introduction to Objects

Object-oriented programming (often called OOP) helps programmers run code sooner and maintain it easier at the cost of making the resulting programs slower. That is to say, a typical program written in an OO language will normally run more slowly than the corresponding one written in a language without objects.

So why would anyone want their programs to run more slowly? Your programs will take less time to read, write, debug, and maintain, and on large projects, these factors are important. How much slowdown are we talking about? Well, that depends. But in general, the more heavily you use objects, the more it will save time for the programmer, and the more it will cost time at runtime. Still, you should remember that computers keep getting faster. Even if using OOP slows down your program, using next year’s hardware will probably make up for it.

The benefits of OOP become worthwhile when your program (including all external libraries and modules) exceeds about N lines of code. Unfortunately, nobody can agree on what the value of N is, but for Perl programs, it’s arguably around 1,000 lines of code. If your whole program is only be a couple hundred lines of code, using objects is probably a waste.

Like references, Perl’s object architecture was grafted on after a substantial amount of existing pre-Perl5 code was already in use, so we had to ensure that it wouldn’t break existing syntax. Amazingly, the only additional syntax to achieve object nirvana is the method call, introduced shortly. But the meaning of that syntax requires a bit of study, so let’s proceed.

The Perl object architecture relies heavily on packages, subroutines, and references, so if you’re skipping around in this book, please go back to the beginning. Ready? Here we go.

Obviously, the castaways can’t survive on coconuts and pineapples alone. Luckily for them, a barge carrying random farm animals crashed on the island not long after they arrived, and the castaways began farming and raising animals.

Let’s let those animals talk for a moment:

sub Cow::speak {
  print "a Cow goes moooo!\n";
}
sub Horse::speak {
  print "a Horse goes neigh!\n";
}
sub Sheep::speak {
  print "a Sheep goes baaaah!\n";
}

Cow::speak;
Horse::speak;
Sheep::speak;

This results in:

a Cow goes moooo!
a Horse goes neigh!
a Sheep goes baaaah!

Nothing spectacular here: simple subroutines, albeit from separate packages, and called using the full package name. Let’s create an entire pasture:

sub Cow::speak {
  print "a Cow goes moooo!\n";
}
sub Horse::speak {
  print "a Horse goes neigh!\n";
}
sub Sheep::speak {
  print "a Sheep goes baaaah!\n";
}

my @pasture = qw(Cow Cow Horse Sheep Sheep);
foreach my $beast (@pasture) {
  &{$beast."::speak"};                # Symbolic coderef
}

This results in:

a Cow goes moooo!
a Cow goes moooo!
a Horse goes neigh!
a Sheep goes baaaah!
a Sheep goes baaaah!

Wow. That symbolic coderef dereferencing there in the body of the loop is pretty nasty. We’re counting on no strict 'refs' mode, certainly not recommended for larger programs.[34] And why was that necessary? Because the name of the package seems inseparable from the name of the subroutine you want to invoke within that package.

Or is it?

A class is a group of things with similar behaviors and traits. For now, let’s say that Class->method invokes subroutine method in package Class. That’s not completely accurate, but you’ll catch on one step at a time. Let’s use it like so:

sub Cow::speak {
  print "a Cow goes moooo!\n";
}
sub Horse::speak {
  print "a Horse goes neigh!\n";
}
sub Sheep::speak {
  print "a Sheep goes baaaah!\n";
}

Cow->speak;
Horse->speak;
Sheep->speak;

And once again, this results in:

a Cow goes moooo!
a Horse goes neigh!
a Sheep goes baaaah!

That’s not fun yet. You’ve got the same number of characters, all constant, no variables. However, the parts are separable now:

my $beast = "Cow";
$beast->speak;                # invokes Cow->speak

Ahh! Now that the package name is separated from the subroutine name, you can use a variable package name. This time, you’ve got something that works even when use strict 'refs' is enabled.

Take the arrow invocation and put it back in the barnyard example:

sub Cow::speak {
  print "a Cow goes moooo!\n";
}
sub Horse::speak {
  print "a Horse goes neigh!\n";
}
sub Sheep::speak {
  print "a Sheep goes baaaah!\n";
}

my @pasture = qw(Cow Cow Horse Sheep Sheep);
foreach my $beast (@pasture) {
  $beast->speak;
}

There! Now all the animals are talking, and safely at that, without the use of symbolic coderefs.

But look at all that common code. Each speak routine has a similar structure: a print operator and a string that contains common text, except for two words. One of OOP’s core features minimizes common code: if you write it only once, you’ll save time. If you test and debug it only once, you’ll save more time.

Now that you’ve learned more about what the method invocation arrow actually does, we’ve got an easier way to do the same thing.

The invocation of:

Class->method(@args)

attempts to invoke the subroutine Class::method as:

Class::method("Class", @args);

(If the subroutine can’t be found, inheritance kicks in, but you’ll learn about that later.) This means that you get the class name as the first parameter or the only parameter, if no arguments are given. You can rewrite the Sheep speaking subroutine as:

sub Sheep::speak {
  my $class = shift;
  print "a $class goes baaaah!\n";
}

The other two animals come out similarly:

sub Cow::speak {
  my $class = shift;
  print "a $class goes moooo!\n";
}
sub Horse::speak {
  my $class = shift;
  print "a $class goes neigh!\n";
}

In each case, $class gets the value appropriate for that subroutine. But once again, you have a lot of similar structure. Can you factor out that commonality even further? Yes—by calling another method in the same class.

You can call out from speak to a helper method called sound. This method provides the constant text for the sound itself:

{ package Cow;
  sub sound { "moooo" }
  sub speak {
    my $class = shift;
    print "a $class goes ", $class->sound, "!\n";
  }
}

Now, when you call Cow->speak, you get a $class of Cow in speak. This, in turn, selects the Cow->sound method, which returns moooo. How different would this be for the Horse?

{ package Horse;
  sub sound { "neigh" }
  sub speak {
    my $class = shift;
    print "a $class goes ", $class->sound, "!\n";
  }
}

Only the name of the package and the specific sound change. So can you share the definition for speak between the cow and the horse? Yes, with inheritance!

Now let’s define a common subroutine package called Animal with the definition for speak:

{ package Animal;
  sub speak {
    my $class = shift;
    print "a $class goes ", $class->sound, "!\n";
  }
}

Then, for each animal, you can say it inherits from Animal, along with the animal-specific sound:

{ package Cow;
  @ISA = qw(Animal);
  sub sound { "moooo" }
}

Note the added @ISA array. We’ll get to that in a minute.

What happens when you invoke Cow->speak now?

First, Perl constructs the argument list. In this case, it’s just Cow. Then Perl looks for Cow::speak. That’s not there, so Perl checks for the inheritance array @Cow::ISA. It’s there, and contains the single name Animal.

Perl next checks for speak inside Animal instead, as in Animal::speak. That found, Perl invokes that subroutine with the already frozen argument list, as if you had said:

Animal::speak("Cow");

Inside the Animal::speak subroutine, $class becomes Cow as the first argument is shifted off. When you get to the step of invoking $class->sound while performing the print, it looks for Cow->sound:

print "a $class goes ", $class->sound, "!\n";
# but $class is Cow, so...
print "a Cow goes ", Cow->sound, "!\n";
# which invokes Cow->sound, returning "moooo", so
print "a Cow goes ", "moooo", "!\n";

and you get your desired output.

This magical @ISA variable (pronounced “is a” not “ice-uh”), declares that Cow “is a” Animal.[35] Note that it’s an array, not a simple single value, because on rare occasions it makes sense to have more than one parent class searched for the missing methods. You’ll learn more about that later.

If Animal also had an @ISA, you can check there too.[36] Typically, each @ISA has only one element (multiple elements means multiple inheritance and multiple headaches), so you get a nice tree of inheritance. (There is also inheritance through UNIVERSAL and AUTOLOAD; see the perlobj manpage for the whole story.)

When you turn on use strict, you’ll get complaints on @ISA because it’s not a variable containing an explicit package name, nor is it a lexical (my) variable. You can’t make it a lexical variable though: it has to belong to the package to be found by the inheritance mechanism.

There are a couple of straightforward ways to handle the declaration and setting of @ISA. The easiest is to just spell out the package name:

@Cow::ISA = qw(Animal);

You can also allow it as an implicitly named package variable:

package Cow;
use vars qw(@ISA);
@ISA = qw(Animal);

If you’re on a recent-enough Perl (5.6 or later), you can use the our declaration to shorten it to:

package Cow;
our @ISA = qw(Animal);

However, if you think your code might be used by people stuck with Perl 5.005 or earlier, it’s be best to avoid our.

If you’re bringing in the class from outside, via an object-oriented module, change:

package Cow;
use Animal;
use vars qw(@ISA);
@ISA = qw(Animal);

to just:

package Cow;
use base qw(Animal);

That’s pretty darn compact. Furthermore, use base has the advantage that it’s performed at compile time, eliminating a few potential errors from setting @ISA at runtime, like some of the other solutions.

Let’s add a mouse that can barely be heard:

{ package Animal;
  sub speak {
    my $class = shift;
    print "a $class goes ", $class->sound, "!\n";
  }
}
{ package Mouse;
  @ISA = qw(Animal);
  sub sound { "squeak" }
  sub speak {
    my $class = shift;
    print "a $class goes ", $class->sound, "!\n";
    print "[but you can barely hear it!]\n";
  }
}

Mouse->speak;

which results in:

a Mouse goes squeak!
[but you can barely hear it!]

Here, Mouse has its own speaking routine, so Mouse->speak doesn’t immediately invoke Animal->speak. This is known as overriding. You use overriding to shadow the method in the derived class (Mouse) because you have a specialized version of the routine, instead of calling the more general base class’s method (in Animal). In fact, you didn’t even need to initialize @Mouse::ISA to say that a Mouse was an Animal at all because all the methods needed for speak are defined completely with Mouse.

You’ve now duplicated some of the code from Animal->speak; this can be a maintenance headache. For example, suppose someone decides that the word goes in the output of the Animal class is a bug. Now the maintainer of that class changes goes to says. Your mice will still say goes, which means the code still has the bug. The problem is that you invoked cut and paste to duplicate code, and in OOP, that is a sin. You should reuse code through inheritance, not by cut and paste.

How can you avoid that? Can you say somehow that a Mouse does everything any other Animal does, but add in the extra comment? Sure!

As your first attempt, you can invoke the Animal::speak method directly:

{ package Animal;
  sub speak {
    my $class = shift;
    print "a $class goes ", $class->sound, "!\n";
  }
}
{ package Mouse;
  @ISA = qw(Animal);
  sub sound { "squeak" }
  sub speak {
    my $class = shift;
    Animal::speak($class);
    print "[but you can barely hear it!]\n";
  }
}

Note that because you’ve stopped using the method arrow, you have to include the $class parameter (almost surely the value of "Mouse“) as the first parameter to Animal::speak,.

Why did you stop using the arrow? Well, if you invoke Animal->speak there, the first parameter to the method is "Animal," not "Mouse“, and when the time comes for it to call for the sound, it won’t have the right class to select the proper methods for this object.

Invoking Animal::speak directly is a mess, however. What if Animal::speak didn’t exist before and was inherited from a class mentioned in @Animal::ISA? For example, suppose the code was:

{ package LivingCreature;
  sub speak { ... }
  ...
}
{ package Animal;
  @ISA = qw(LivingCreature);
  # no definition for speak(  )
  ...
}
{ package Mouse;
  @ISA = qw(Animal);
  sub speak {
    ...
    Animal::speak(  ... );
  }
  ...
}

Because you no longer use the method arrow, you get one and only one chance to hit the right subroutine. You’ll look for it in Animal, and not find it, and the program aborts.

The Animal classname is now hardwired into the subroutine selection. This is a mess if someone maintains the code, changing @ISA for Mouse, and didn’t notice Animal there in speak. Thus, this is probably not the right way to go.

A better solution is to tell Perl to search from a different place in the inheritance chain:

{ package Animal;
  sub speak {
    my $class = shift;
    print "a $class goes ", $class->sound, "!\n";
  }
}
{ package Mouse;
  @ISA = qw(Animal);
  sub sound { "squeak" }
  sub speak {
    my $class = shift;
    $class->Animal::speak(@_);
    print "[but you can barely hear it!]\n";
  }
}

Ahh. As ugly as this is, it works. Using this syntax, start with Animal to find speak and use all of Animal’s inheritance chain if not found immediately. The first parameter is $class (because you’re using an arrow again), so the found speak method gets Mouse as its first entry and eventually works its way back to Mouse::sound for the details.

This isn’t the best solution, however. You still have to keep the @ISA and the initial search package in sync (changes in one must be considered for changes in the other). Worse, if Mouse had multiple entries in @ISA, you wouldn’t necessarily know which one had actually defined speak.

So, is there an even better way?

By changing the Animal class to the SUPER class in that invocation, you get a search of all your superclasses (classes listed in @ISA) automatically:

{ package Animal;
  sub speak {
    my $class = shift;
    print "a $class goes ", $class->sound, "!\n";
  }
}
{ package Mouse;
  @ISA = qw(Animal);
  sub sound { "squeak" }
  sub speak {
    my $class = shift;
    $class->SUPER::speak;
    print "[but you can barely hear it!]\n";
  }
}

Thus, SUPER::speak means to look in the current package’s @ISA for speak, invoking the first one found if there’s more than one. In this case, you look in the one and only base class, Animal, find Animal::speak, and pass it "Mouse" as its only parameter.

In that last example, had there been any additional parameters to the speak routine (like how many times, or in what pitch for singing, for example), the parameters would be ignored by the Mouse::speak routine. If you want them to be passed uninterpreted to the parent class, you can add it as a parameter:

$class->SUPER::speak(@_);

This invokes the speak routine of the parent class, including all the parameters that you’ve not yet shifted off of your parameter list.

Which one is correct? It depends. If you are writing a class that simply adds to some of the parent class behavior, it’s best to simply pass along arguments you haven’t dealt with. However, if you want precise control over the parent class behavior, you should determine the argument list explicitly, and pass it.

So far, you’ve seen the method arrow syntax:

Class->method(@args);

or the equivalent:

my $beast = "Class";
$beast->method(@args);

which constructs an argument list of:

("Class", @args)

and attempts to invoke:

Class::method("Class", @args);

However, if Class::method is not found, @Class::ISA is examined (recursively) to locate a package that does indeed contain method, and that subroutine is invoked instead.

Chapter 9 shows how to distinguish the individual animals by giving them associated properties, called instance variables.

The answers for all exercises can be found in Section A.7.



[34] Although all examples in this book should be valid Perl code, some examples in this chapter will break the rules enforced by use strict to make them easier to understand. By the end of the chapter, though, you’ll learn how to make strict-compliant code again.

[35] ISA is actually a linguistic term. Once again, Larry Wall’s background as a linguist has come back to influence Perl.

[36] The search is recursive, depth-first and left to right in each @ISA.