ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы.



Perl Cookbook

Perl CookbookSearch this book
Previous: 12.19. Program: Finding Versions and Descriptions of Installed ModulesChapter 13Next: 13.1. Constructing an Object
 

13. Classes, Objects, and Ties

All the world over, I will back the masses against the classes.

- William E. Gladstone Speech at Liverpool, 28 June 1886

13.0. Introduction

Along with references and modules, release 5.000 of Perl added objects. As usual, Perl doesn't try to enforce one true style but embraces many. This helps more people do their job the way they want to do it.

You don't have to use objects to write programs, unlike Java, where programs are instances of objects. If you want to, though, you can write Perl programs that use nearly every weapon in the object-oriented arsenal. Perl supports classes and objects, single and multiple inheritance, instance methods and class methods, access to overridden methods, constructors and destructors, operator overloading, proxy methods through autoloading, delegation, a rooted hierarchy for all objects, and two levels of garbage collection.

You can use as many or as few object-oriented techniques as you want and need. Ties are the only parts of Perl where you must use object orientation. And even then, only the module implementor need be aware of this; the casual user gets to remain blissfully unaware of the internal mechanics. Ties, discussed in Recipe 13.15, let you transparently intercept access to a variable. For example, you can use ties to make a hash that allows lookups by key or value.

Under the Hood

If you ask ten people what object orientation is, you'll get ten different answers. People bandy about terms like abstraction and encapsulation, trying to isolate the basic units of object-oriented programming languages and give them big names to write papers and books about. Not all object-oriented languages offer the same features, yet they are still deemed object-oriented. This, of course, produces more papers and books.

We'll follow the nomenclature used in Perl's documentation, the perlobj (1) manpage, and Chapter 5 of Programming Perl, "Libraries, Modules, and Classes." An object is a variable that belongs to a class. Methods are functions associated with a class or object. In Perl, a class is a package  - and usually a module. An object is a reference to something that's been blessed into a class. Blessing associates a referent with a class. This is done with the bless function, which takes one or two arguments. The first is a reference to the thing to bless, and the optional second argument is the package to bless it into.

$object = {};                       # hash reference
bless($object, "Data::Encoder");    # bless $object into Data::Encoder class
bless($object);                     # bless $object into current package

The class name is the package name (Data::Encoder in the example above). Because classes are modules (usually), the code for the Data::Encoder class resides in the file Data/Encoder.pm. As with traditional modules, the directory structure is purely for convenience; it implies nothing about inheritance, variable sharing, or anything else. Unlike a traditional module, though, an object module seldom if ever uses the Exporter. Access should be through method calls only, not imported functions or variables.

Once an object has been blessed, calling the ref function on its reference returns the name of its class instead of the fundamental type of referent:

$obj = [3,5];
print ref($obj), " ", $obj->[1], "\n";
bless($obj, "Human::Cannibal");
print ref($obj), " ", $obj->[1], "\n";

ARRAY 5
Human::Cannibal 5

As you can see, you can still dereference a reference once it has been blessed. Most frequently, objects are implemented as blessed hash references. You may use any kind of reference you want, but hash references are the most flexible. They let you have arbitrarily named data fields in an object.

$obj->{Stomach} = "Empty";   # directly accessing an object's contents
$obj->{NAME}    = "Thag";        # uppercase field name to make it stand out (optional)

Although Perl permits it, it's considered poor form for any code outside the class to directly access the contents of an object. The point of objects, everyone agrees, is to give you a nominally opaque handle to something that you access through designated methods only. This lets the maintainer of the class change its implementation without needing to change all application code that uses the class.

Methods

To call a method, use ->. Here, we call the encode() method of $object with the argument "data" and store the return value in $encoded :

$encoded = $object->encode("data");

This is an object method, because we call the method on an object. We can also have class methods, methods called on class names.

$encoded = Data::Encoder->encode("data");

Invoking a method calls the function in the corresponding class, implicitly passing as the initial argument either a reference for object methods or a string for class methods. Recipe 13.7 shows how to make method calls where the method is determined at runtime.

Most classes provide constructor methods, which return new objects. Unlike some object-oriented languages, constructor methods in Perl are not specially named. In fact, you can name them anything you like. C++ programmers have a penchant for calling their constructors in Perl new. We recommend that you name your constructors whatever makes sense in the context of the problem you're solving. For example, constructors in the Tk extension to Perl are named after the widgets they create. A less common approach is to export a function with the same name as the class; see "Example: Overloaded StrNum Class" in Recipe 13.14 for an example.

A typical constructor looks like this:

sub new {
    my $class = shift;
    my $self  = {};         # allocate new hash for object
    bless($self, $class);
    return $self;
}

Call the constructor with:

$object = Class->new();

If there isn't any inheritance or other monkey business working behind the scenes, this is effectively the same as:

$object = Class::new("Class");

The new() function's first argument here is the class name to bless the new reference into. A constructor should pass that string as the second argument to bless().

Recipe 13.1 also talks about functions that return blessed references. Constructors don't have to be class methods, and writing object methods that return new objects have a number of uses, as discussed in Recipe 13.6.

A destructor is a subroutine that runs when an object's referent is garbage collected. Unlike constructors, you have no choice in naming it. You must name your destructor method DESTROY. This method, if it exists, will be called for all objects immediately prior to memory deallocation. Destructors, described in Recipe 13.2, are optional.

Some languages syntactically allow the compiler to restrict access to a class's methods. Perl does not  - it allows code to call any method of an object. The author of a class should document clearly the public methods (those which may be used), and the user of a class should avoid undocumented (implicitly private) methods.

Perl doesn't distinguish between methods that can be called on a class (class methods) and methods that can be called on an object (instance methods). If you want a particular method to be called as a class method only, do something like this:

sub class_only_method {
    my $class = shift;
    die "class method called on object" if ref $class;
    # more code here
} 

If you want to allow a particular method to be called as an instance method only, do something like this:

sub instance_only_method {
    my $self = shift;
    die "instance method called on class" unless ref $self;
    # more code here
} 

If your code calls an undefined method on an object, Perl won't complain at compile time; the program will instead trigger an exception at run time. Likewise, the compiler can't catch situations where you pass a non-prime value to a method expecting a prime number. Methods are just function calls whose package is determined at run time. Like all indirect functions, they have no prototype checking  - because that happens at compile time. Even if method calls were aware of prototypes, in Perl the compiler is unable to automatically check the precise types or ranges of arguments to functions. Perl prototypes are used to coerce a function argument's context, not to check ranges. Recipe 10.11 details Perl's strange perspective on prototypes.

You can prevent Perl from triggering an exception for undefined methods by using the AUTOLOAD mechanism to catch calls to nonexistent methods. We show an application of this in Recipe 13.11.

Inheritance

Inheritance defines a hierarchy of classes. Calls to methods not defined in a class search this hierarchy for a method of that name. The first method found is used. Inheritance means allowing one class to piggy-back on top of another so you don't have to write the same code again and again. This is a form of software reuse, and therefore related to Laziness, the principal virtue of a programmer.

Some languages provide special syntax for inheritance. In Perl, each class (package) can put its list of superclasses (parents in the hierarchy) into the package global (not a my) variable @ISA. This list is searched at runtime when a call is made to a method not defined in the object's class. If the first package listed in @ISA doesn't have the method but that package has its own @ISA, Perl looks first in that package's own @ISA, recursively, before going on.

If the inheritance search fails, the same check is run again, this time looking for a method named AUTOLOAD. The lookup sequence for $ob->meth(), where $ob is of class P, is:

  • P::meth

  • All packages S in @P::ISA, recursively, for any S::meth()

  • UNIVERSAL::meth

  • The P::AUTOLOAD subroutine

  • All packages S in @P::ISA, recursively, for any S::AUTOLOAD()

  • The UNIVERSAL::AUTOLOAD subroutine

Most classes have just one item in their @ISA array, a situation called single inheritance. Classes with more than one element in @ISA represent multiple inheritance. The benefits of multiple inheritance are widely contested, but it is supported by Perl.

Recipe 13.9 talks about the basics of inheritance and designing a class so it can be easily subclassed. In Recipe 13.10 we show how a subclass can call overridden methods in its superclasses.

Perl doesn't support inheritance of data values. A class can, but should not, touch another's data directly. This violates the envelope and ruins the abstraction. If you follow the advice in Recipes Recipe 13.10 and Recipe 13.12, this won't be much of an issue.

A Warning on Indirect Object Notation

The indirect notation for method calls:

$lector = new Human::Cannibal;
feed $lector "Zak";
move $lector "New York";

is an alternative syntax for:

$lector = Human::Cannibal->new();
$lector->feed("Zak");
$lector->move("New York");

This indirect object notation is appealing to English speakers and familiar to C++ programmers (who use new this way). Do not be seduced. It has two grave problems. One is that it follows the same quirky rules as the filehandle slot in print and printf:

printf STDERR "stuff here\n";

This slot, if filled, must contain a bare symbol, a block, or a scalar variable name; it can't be any old scalar expression. This can lead to horribly confusing precedence problems, as in these next two lines:

move $obj->{FIELD};                 # probably wrong
move $ary[$i];                      # probably wrong

Surprisingly, those actually parse as:

$obj->move->{FIELD};                # Surprise!
$ary->move->[$i];                   # Surprise!

rather than as you might have expected:

$obj->{FIELD}->move();              # Nope, you wish
$ary[$i]->move;                     # Nope, you wish

The second problem is that Perl must guess at compile time whether name and move are functions or methods. Usually Perl gets it right, but when it doesn't, you get a function call compiled as a method, or vice versa. This can introduce incredibly subtle bugs that are hard to unravel. The infix arrow notation using -> doesn't suffer from either of these disturbing ambiguities, so we recommend you use it exclusively.

Some Notes on Object Terminology

In the object-oriented world, many words describe only a few concepts. If you've programmed in another object-oriented language, you might like to know how familiar terms and concepts map onto Perl.

For example, it's common to call objects instances of a class and those objects' methods instance methods. Data fields peculiar to each object are often called instance data or object attributes, and data fields common to all members of that class are class data, class attributes, or static data members.

Also, base class, generic class, and superclass all describe the same notion (a parent or similar ancestor in the inheritance hierarchy), whereas derived class, specific class, and subclass describe the opposite relationship (a child or descendent in the inheritance hierarchy).

C++ programmers have static methods, virtual methods, and instance methods, but Perl only has class methods and object methods. Actually, Perl only has methods. Whether a method acts as a class or object method is determined solely by actual usage. You could call a class method (one expecting a string argument) on an object (one expecting a reference), or vice versa, but you shouldn't expect reasonable results if you do.

A C++ programmer thinks about global (class) constructors and destructors. These correspond to module initialization code and per-module END{} blocks respectively.

From the C++ perspective, all methods in Perl are virtual. This is why their arguments are never checked for function prototypes as regular built-in and user-defined functions can be. Prototypes are checked by the compiler at compile time. You can't determine until run time the function that a method has called.

Philosophical Aside

In its OO programming, Perl gives you a lot of freedom: the ability to do things more than one way (you can bless any data type to make an object), to inspect and modify classes you didn't write (adding functions to their packages), and to use these to write tangled pits of misery  - if that's really what you want to do.

Less flexible programming languages are usually more restrictive. Many are fanatically devoted to enforced privacy, compile-time type checking, complex function signatures, and a smorgasbord of other features. Perl doesn't provide these things with objects because it doesn't provide them anywhere else, either. Keep this in mind if you find Perl's object-oriented implementation weird. You only think it's weird because you're used to another language's philosophy. Perl's treatment of OO is perfectly sensible  - if you think in Perl. For every problem that you can't solve by writing Perl as though it were Java or C++, there is a native Perl solution that works perfectly. The absolutely paranoid programmer can even have complete privacy: the perltoot (1) manpage describes how to bless closures to produce objects that are as private as those in C++ (and more so).

Perl's objects are not wrong; they're differently right.

See Also

The general literature on object-oriented programming rarely refers directly to Perl. The documentation that came with Perl is a good place to begin learning about object-oriented programming, particularly the object tutorial perltoot (1). For a reference, read perlobj (1) and Chapter 5 of Programming Perl. You might need it when you read perlbot (1), which is full of object-oriented tricks.

Chapters 7 and 8 of Advanced Perl Programming includes a discussion of object-oriented programming in Perl for those who have encountered objects before.


Previous: 12.19. Program: Finding Versions and Descriptions of Installed ModulesPerl CookbookNext: 13.1. Constructing an Object
12.19. Program: Finding Versions and Descriptions of Installed ModulesBook Index13.1. Constructing an Object