13. Classes, Objects, and Ties
Contents:
All the world over, I will back the masses against the classes. - William E. Gladstone Speech at Liverpool, 28 June 1886 13.0. IntroductionAlong 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 HoodIf 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 $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 (
Once an object has been blessed, calling the $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 $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 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 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 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 . InheritanceInheritance 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
If the inheritance search fails, the same check is run again, this time looking for a method named
Most classes have just one item in their 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 NotationThe indirect notation for method calls: $lector = new Human::Cannibal; feed $lector "Zak"; move $lector "New York"; is an alternative syntax for:
$lector = Human::Cannibal->
This indirect object notation is appealing to English speakers and familiar to C++ programmers (who use 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}->
The second problem is that Perl must guess at compile time whether Some Notes on Object TerminologyIn 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 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 AsideIn 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 AlsoThe 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. |
|