Previous Page Next Page

14.2. Classes, Objects, and Methods

14.2.1. Real World

Suppose you want to build a house. First, you would buy a piece of property located at a specific address. Then you would hire an architect or buy a program for your computer to help design the house. You would decide what type, style, how many rooms, doors, windows, etc. After you design the house, you will hire a contractor to build the house. Once it's built, you have access to your new house, you can go inside, set up housekeeping, paint it, clean it, furnish it, remove trash, landscape it, whatever. But before you can really do anything in or around your house, you must build it. Later you may want to add a new room, show it for sale, demolish it, etc. Since you have the blueprints, you could find another piece of property and build a house just like yours, maybe paint it a different color, change the landscaping, etc. In fact, you could build a whole development with houses like yours from the same design, each house identified by its unique address.

In an object-oriented language, the house would be the object, a noun. The style, number of rooms, type, etc., would be the properties that describe the object, like adjectives, and the verbs, such as paint the house, move into the house, show the house, describe the "behaviors" for the object.

All of this will become clearer as we examine a number of examples and discuss how Perl creates, maniuplates, and destroys objects.

14.2.2. The Steps

This chapter will discuss a number of topics in detail. For the big picture, the following steps are necessary to create the new data type called object and define what it can do:

1.
Determine what your object is and what it is supposed to accomplish (design).

2.
Create the new object (constructor) in a package, called a class.

3.
Describe the object; i.e., give it properties, attributes (adjectives).

4.
Bless the object (make the data type an object).

5.
Define the functions (verbs), what it can do or what can be done to it (methods).

6.
Use the object (define the user interface, call the methods).

7.
Reuse the object (inheritance).

8.
Destroy the object (remove the object from memory).

14.2.3. Classes and Privacy

A Perl class is just a package. The terms are interchangeable. A class is stored in a .pm module, and the class name is the same as the module (minus the .pm extension). If you want to distinguish between the two terms, a class is a package containing special subroutines called methods that manipulate objects. A Perl class normally consists of:

  1. The data that describes the object.

  2. A function, called "bless," that creates the object.

  3. Special subroutines, called "methods," that know how to create, access, manipulate, and destroy the object.

Figure 14.1. What makes up a class? The .pm file.


Since a class is really just a package, it has its own symbol table, and the data or routines in one class can be accessed in another via the double colon (Perl 5) or the single apostrophe (Perl 4).

Unlike other languages, Perl does not strictly monitor public/private borders within its modules.[2] To keep variables private, the my function is used. The my variables exist only within the innermost enclosing block, subroutine, eval, or file. The my variables cannot be accessed from another package by using the double colon (or single apostrophe), because my variables are not related to any package; they are not stored in the symbol table of the package in which they are created.

[2] Wall, L., and Schwartz, R. L., Programming Perl, 2nd ed., O'Reilly & Associates: Sebastopol, CA, 1998, p. 287.

Example 14.1.

    #!/bin/perl
1   package main;

2   $name = "Susan";
3   my $birthyear = 1942;

4   package nosy;
5   print "Hello $main::name.\n";
6   print "You were born in $main::birthyear?\n";

(Output)
5   Hello Susan.
6   You were born in ?

Explanation

  1. The package is main.

  2. The scalar $name is global in scope within this package.

  3. The scalar $birthyear is local to this and any enclosing inner blocks.

  4. The package nosy is declared. Its scope is from the declaration to the bottom of the file.

  5. The global variable $name can be accessed by qualifying it with its package name and two colons.

  6. The scalar $birthyear is inaccessible to this package via the symbol table. It was declared with the my function in a different package, main, and is not associated with any symbol table but is stored in a private scratch pad created within the enclosing block.

14.2.4. Objects

To begin with, an object in Perl is created by using a reference. A reference, if you recall, is a scalar that holds the address of some variable. It's a pointer. A reference might also point to a variable or subroutine that has no name, called an anonymous variable. For example, here is a reference, called $ref, to an anonymous hash consisting of two key/value pairs:

my $ref  = { "Owner"=>"Tom",  "Price"=>"25000" };

To access a value in the anonymous hash, the reference (pointer) $ref can be dereferenced by using the arrow operator as follows:

$ref->{"Owner"}

To make a Perl object, first a reference is created. The reference normally is assigned the address of an anonymous hash (although it could be assigned the address of an array or scalar or subroutine). The hash will contain the data members, properties, of the object. In addition to storing the address of the hash, the reference must know what package it belongs to. This is done by creating the reference and then "blessing" it into a package. The bless function acts on the "thing" being referenced in the package, not the reference itself. It creates an internal pointer to track what package the thing (object) belongs to. The object is the thing (usually a hash) that was blessed into the class (package). If the package is not listed as the second argument, the bless function assumes the current package. It returns a reference to the blessed object. (See "The bless Function" for a complete discussion of bless.)

my $ref  = { Owner => "Tom",  Price => 250000 };    # This is the object
bless( $ref, Class);   # The object is blessed into the package named Class
return $ref;           # A reference to the object is returned

Once an object has been blessed, you don't have to export symbols with the @EXPORT_OK or @EXPORT arrays. In fact, as a general rule, if the module is trying to be object-oriented, then export nothing.

The House Class

Figure 14.2 demonstrates how you might visualize a House class. First you would create a package. This package is called House and is found in a file called House.pm. In OO lingo, the package will now be called a class. (Note the class name must be same as the filename without the .pm extension.) To illustrate encapsulation, the house object is enclosed around the data that describes it. The properties, or attributes, describe characteristics of the object, such as its owner, style, size, color, and so forth. In our example, the house properties are Owner, Style, and Price. In Perl, the object is often described with an anonymous hash, where the key/value pairs are the properties of the object. Outside of the house, subroutines are listed. In the OO world, these subroutines are called public methods, and they are the way you get access to the object. They can get access to the object but not until it exists. They often describe "behaviors" of the object; i.e., what it can do or what can be done to it. In fact, the methods should be the only way to get access to the object. For our house object, one method to access the house might be to move in, another to clean it, another to display it, and so on. Methods in Perl are just glorified subroutines.

Figure 14.2. A House class.


There are no special Perl keywords called private, public, or protected as in other OO languages. Perl's package mechanism makes up the class where the data and subroutines, called methods, are stored. The my function keeps variables lexically scoped, and the bless function guarantees that when the object is created, it will know to which class it belongs. In summary, the object is usually a pointer to an anonymous hash, array, or scalar and is manipulated by special functions called methods that have access to the object via the pointer.

14.2.5. The bless Function

Think of the bless function as creating a new data type called an object. In Figure 14.2 the House object is created by first giving it properties with an anonymous hash and getting back a pointer, an address. Think of it as the address where the house is located, only in our program, the memory address. The bless goes to that address and creates a House object. Once you've blessed a scalar, array, hash, etc., it is transformed into an object. To be more technical, the first argument to the bless function must be pointer. The bless function internally tags whatever the pointer is pointing at (called the referent) with a reference to the package where it belongs. This is how an object is created. If the package (class) is not listed as the second argument, the bless function tags the object as belonging to the current package. The bless function uses the reference to find the object and returns a reference to the object. Since the blessing associates the object with a particular package (class), Perl will always know to what package the object belongs. An object can be blessed into one class and then reblessed into another and then another, and so on, but an object can belong to only one class at a time.

Format

bless REFERENCE, CLASSNAME
bless REFERENCE

Example 14.2.

my $reference = {};
return bless( $reference, $class);

 


Example 14.3 illustrates how to create an object. First we create an anonymous hash, then bless it into a package, and use the ref function to see if the object is truly in the package.

Example 14.3.

(The Script)
1   package House;          # Package declaration

2   my $ref = { "Owner"=>"Tom", #Anonymous hash; data for the package
                "Price"=>"25000", # Properties/attributes
             };
3   bless($ref, House);

    # The bless function creates the object. The hash referenced by
    # $ref  is the object. It is blessed into
    # the package; i.e., an internal pointer is created to keep track
    # of the package where it belongs.

4   print "The bless function tags the hash with its package
        name.\n";
5   print "The value of \$ref is: $ref.\n";
6   print "The ref function returns the class (package) name:",
        ref($ref), ".\n";

(Output)
4   The bless function tags the hash with its package name.
5   The value of $ref is: House=HASH(0x5a08a8).
6   The ref function returns the class (package) name: House.

Explanation

1The House package is declared. It is the class.
2A reference, $ref, is assigned the address of an anonymous hash, consisting of two key/value pairs. These values represent the properties that describe the object.
3The bless function takes either one or two arguments. The first argument is a reference and the second argument is the name of the package. If the second argument is missing, the current package is assumed.[a] In this example, the current package is called House. Now the reference knows that the object it references (the object) is in the House package.
5The value of the reference (the address of the object) is printed. It is a reference to a hash in the House package; simply put, it is a pointer to the new House object.
6The ref function returns the name of the package if its argument, a pointer, is an object; i.e., it has been blessed.


[a] It is recommended that the two-argument form for the bless function be used, especially with inheritance. (See "Inheritance" on page 460.)

[a] It is recommended that the two-argument form for the bless function be used, especially with inheritance. (See "Inheritance" on page 460.)

14.2.6. Methods

Definition

A method is a subroutine that operates on an object. It is a special subroutine that belongs to a class and expects its first argument to be either a package name or a reference to an object. This argument is sent by Perl implicitly. Otherwise, it looks like any other subroutine. A method is used primarily to create an object, to assign or change the data in the object, or to retrieve data from an object.[3]

[3] Unlike C++, Perl doesn't provide any special syntax for a method definition.

Types of Methods

There are two types of methods: class (or static) methods and instance (or virtual) methods.[4] The class method expects a class name as its first argument, and the instance method expects an object reference as its first argument.

[4] What you call a method type depends on what book you read. Larry Wall categorizes methods as class methods, instance methods, and dual-nature methods.

A class method is a subroutine that affects the class as a whole; for example, it can create an object or act on a group of objects. The class method expects a class name as its first argument. In object-oriented programs, a constructor function is a class method used to create an object. In Perl, this method is commonly called new, although you can call it anything you like. The creation of the object is often called the instantiation of the object, or instance, of the class.

Object-oriented programs use instance methods (also called access methods) to control the way the object's data is assigned, modified, and retrieved. You can't use an instance method until you have created the object. The method that creates the object is called a constructor. It returns a reference to the object. Once the reference to the newly created object is returned, the instance method uses that reference, often called $this or $self, to get at the object. The instance method expects a reference to the object as its first argument. It then manipulates an object by using the reference to it.

Invoking Methods

Perl provides a special syntax for invoking methods. Instead of using the package::function syntax, methods are invoked in one of two ways: class method invocation or instance method invocation. There are two types of syntax for each method call: object-oriented syntax and indirect syntax. If you are using objects, either syntax for these method calls is acceptable. The older way of calling methods with the double colons is not recommended.

Something to remember: A method, unlike an ordinary subroutine, is always sent one argument implicitly, either the name of the class or a reference to the object. If, for example, you call a method with three arguments, four arguments are really sent, the first one being the value found on the left-hand side of the arrow when using the object-oriented style.

Class Method Invocation

Assume the method name is called new and the return value, $ref, is a pointer to the object.

1) $ref = class->new( list of arguments );   # object-oriented syntax
2) $ref = new class ( list of arguments );   # indirect syntax

If the class is called House, Perl translates

        $ref = House->new();

to

        $ref = House::new(House);

Instance Method Invocation

Assume the method name is called display and the reference to the object is called $ref.

1) $ref->display( list of arguments );    # object-oriented syntax
2) display $ref ( list of arguments );    # indirect syntax

The first example for each method is called the object-oriented; the second example, using the arrow operator, is called the indirect syntax syntax.

When Perl sees one of the preceding methods being invoked, it knows what class the object belongs to, because the object was blessed (an internal pointer is tracking where it is).[5]

[5] The capability of Perl to call the appropriate module's function is called runtime binding, according to Srinivasan, S., Advanced Perl Programming, O'Reilly & Associates: Sebastopol, CA, 1997.

If you call either

display $ref (arguments...);

or

$ref->display(arguments...);

and $ref points to an object in a class called House, Perl translates that to

House::display($ref, arguments...);

14.2.7. What an Object-Oriented Module Looks Like

Figure 14.3 illustrates the layout of a typical object-oriented module. The file where the module is created is a .pm file. In this example, the .pm file is House.pm. The file consists of one package declaration. The package will be called a class; so, this is the House class. The class consists of subroutines, now called methods. The first type of method, called new, is a constructor method. It is the method that will define and create (construct) the object. When a user of this module calls the method new, he will get back a reference to the newly created House object (the address of the house). The new method gets the name of the class as it first argument. This method not only creates the object but also blesses the object so that the object always knows what class (package) it belongs to. (See "The bless Function" on page 429.) The second two methods are called access, or instance, methods. These are the methods that store and fetch the data from the object. You can't use these methods until you have created an instance of the object. (You can't move into the house or show it off until you have built it.) Once you, the user, have a reference to the object, the reference is used to call the instance methods.

Figure 14.3. A House class and the user of the class.


Continuing in Figure 14.3, we see that the object's data will be described in an empty anonymous hash (although any other data type might be used), and the address of the object will be assigned to a local (my) reference. (The object's data will be assigned later with an instance method called set_data.) The bless function will tag the object with the name of the class where it belongs and return a pointer to the object; i.e., when the user of the module calls the constructor, he gets back a pointer to the newly created object. The constructor is said to "instantiate" the object (create a new house). The user can create as many objects as he wants, and Perl will give him a unique address for each. Once an object is created, the instance methods (often called setters and getters) will be used to manipulate the object. The user calls the instance methods to store data in the object and to retrieve data from the object. The instance methods must have a reference to the object in order to access the right object. The instance methods always get a reference to the object as their first argument.

There are many ways the module can be designed. This is just one simple approach.

The Class Constructor Method

Constructor is an OOP term for a class method that creates and initializes an object into a class. There is no special syntax for a constructor. It is just a method that is used to get a reference blessed into a package. The first method in a Perl class (i.e., the first subroutine in a package) is normally the one that creates the reference (to the object) and blesses it into the package. This method is often called new, since it makes a new "thing," but could be called anything you want, such as create, construct, initiate, and so forth.

The object that is blessed into the new subroutine is usually an anonymous hash or anonymous array. The anonymous hash or array is assigned the data that describes the object. The data is often described as the properties, or attributes, of the object. When referred to collectively, the attributes define the state of the object.

Example 14.4.

(The Module: House.pm)
1   package House;                 # Class

2   sub new {                      # Class method called a constructor
3       my $class = shift;
4       my $ref={"Owner"=>undef,   # Attributes of the object
                 "Price" =>undef,  # Values will be assigned later
                };
5       bless($ref, $class);
                        # $ref now references an object in this class
6       return $ref;    # A reference to the object is returned

    }
    1;
----------------------------------------
(The User of the Module)
    #!/usr/bin/perl
7   use House;
8   my $houseref = House->new();
    # call the new method and create the object
9   # my $houseref = new House; another way to call the new method
10  print "\$houseref in main belongs to class ",
             ref($houseref),".\n";

(Output)
10  $houseref in main belongs to class House.

Explanation

  1. The package House is declared. It can be called a class because it contains a method that will bless a reference.

  2. The subroutine new is called a constructor method in OOP lingo. The primary job of a constructor is to create and initialize an object. In Perl, it doesn't really have any special syntax. This is called a class method, since its first argument is the name of the class. It is a subroutine that blesses a referenced "thing" (object) into a class and returns a reference to it. The subroutine is called a method and the "thing" it blessed is an object. The package is called a class.

  3. The first argument received by this type of subroutine is the name of the package or class, in this case House. This is another difference between a method and a subroutine. The first argument of a method is the name of either a class or an object.

  4. The reference $ref is assigned the address of an anonymous hash (object). The keys are assigned undef, meaning the values at this time are undefined and will be defined later.

  5. The "thing" $ref is pointing at is blessed into the class $class and transformed into an object.

  6. A pointer to the object is returned to the caller of the constructor method.

  7. This is the script where the House module will be used. After the shbang line, the use statement causes the module House.pm to be loaded into memory.

  8. The new constructor method is called with the class/package name House as its first argument. It returns a reference, $houseref, which points to the anonymous hash, the new object. The name of the class is implicitly sent as the first argument to the new() method.

  9. Perl translates $houseref = House–>new() to $houseref=House::new(House); . This line is commented out. It demonstrates another way, called the indirect syntax, in which to invoke a method. You can use either style.

  10. The ref function returns the name of the class (package) if the reference has been blessed into that class.

The Class and Instance Methods

To review: The class methods, also called static methods, are methods, or subroutines, that don't require the instance of an object in order to function. They are independent functions that act on behalf of the class. A function that calculates a paycheck or gets a list of names from a database is an example of a class method. The most common class method is called a constructor method, a method used to create the object. It takes a class (package) name as its first argument and functions for the entire class.

Object-oriented programs often use access, or instance, methods to control the way data is modified, retrieved, and displayed. In order to manipulate an object, the instance, or access, methods require an instance of an object; that is, a reference to an object that has already been created.

If the data need to be represented in a different way in one of the methods, the other methods needs not be affected, as long as the interface provided to the user remains the same. The instance methods in the following examples are used as access functions that display the data members of the class. Instance methods take an object reference as their first argument. Look at the value on the left-hand side of the -> where the method is being called. That value is the object, and it is implicitly sent as the first argument to the method being called. (If the value on the left-hand side of the -> is a class name, then the class name is sent as the first argument to the method; e.g., a constructor sends the class as its first argument.)

Example 14.5.

    #!/usr/bin/perl
1   package House;
2   sub new{          # Class/Static method
3      my $class = shift;
4      my $ref={};   # Anonymous and empty hash
5      bless($ref);
6      return $ref;
    }
7   sub set_owner{    # Instance/Virtual method
8      my $self = shift;
9      print "\$self is a class ", ref($self)," reference.\n";
10     $self->{"Owner"} = shift;
    }
11  sub display_owner {
12     my $self = shift;
                   # The object reference is the first argument
13     print $self->{"Owner"},"\n";
    }
    1;

--------------------------------------------------------------------

(The Script)
    #!/usr/bin/perl
    # The user of the class
14  use House;
15  my $house = House->new;             # Call class method
16  $house->set_owner ("Tom Savage");   # Call instance method
17  $house->display_owner;              # Call instance method

(Output)
9   $self is a class House reference.
13  Tom Savage

					  

Explanation

  1. The package House is declared. This can also be called the class House.

  2. The class method new is a constructor. It creates a reference and blesses it into the class House.

  3. The $class variable is assigned the name of the class, the first argument to the new constructor.

  4. The reference $ref is assigned an anonymous, empty hash.

  5. The "thing" (anonymous hash) referenced by $ref is blessed into the class House. The "thing" becomes the new object.

  6. A reference to the object will be returned to the caller.

  7. The instance method set_owner is defined.

  8. A reference to the object is shifted from the @_ array into $self. Now the instance method can manipulate the object because it has a reference to it.

  9. The return from the ref function is the name of the class House. The class name is returned by ref only if the object has been blessed.

  10. The second argument is shifted from the @_ array. Tom Savage is assigned as a value to the key Owner. This instance method is then used to assign data to the object (called a "setter").

  11. The instance method display_owner is called to access the object's data; in this example, to print the value in the Owner field of the anonymous hash.

  12. The object reference is the first argument to the method. It is shifted from the @_ array into $self.

  13. The value in the key Owner field is displayed.

  14. This program uses the House.pm module.

  15. The new constructor method is called and a reference to a House object is returned; that is, a reference to an anonymous hash in the House class. The constructor method, new, always passes at least one argument, the name of the class. House–>new() translates to House::new(House).

  16. The instance method set_owner is called with the argument Tom Savage. Remember, the first argument passed to an instance method is always a reference to the object, making Tom Savage the second argument: $house–>set_owner ("Tom Savage") translates to House::set_owner($house, "Tom Savage");

  17. The display method is called, which displays the value of the anonymous hash, Tom Savage.

Passing Parameters to Constructor Methods

Instance variables are used to initialize the object when it is created. In this way, each time the object is created, it can be customized. The properties that describe the object may be passed as arguments to the constructor method and assigned to instance variables. They are called instance variables because they come into existence when the object is created, or instantiated. Either an anonymous hash or an anonymous array is commonly used to hold the instance variables. In the following example, the object "has a" or "contains a" owner and a price.

Example 14.6.

(The Module: House.pm)
1   package House;
2   sub new{         # Constructor  method
3      my $class = shift;
4      my ($owner, $salary) = @_;      # Instance variables
5      my $ref={"Owner"=>$owner,       # Instance variables to
                "Price"=>$price,       # initialize the object
       };
6      bless($ref, $class);
7      return $ref;
    }
8   sub display_object {       # An instance method
9      my $self = shift;      # The name of the object is passed
10     while( ($key, $value)=each %$self){
          print "$key: $value \n";
       }
    }
    1;

-------------------------------------------------------------------

(The Script)
    #!/usr/bin/perl
    # User of the class; another program
11  use House;
    # Documentation explaining how to use the House
    # package is called the public interface.
    # It tells the programmer how to use the class.
    # To create a House object requires two arguments,
    # an owner and a price.
    # See "Public User Interface—Documenting Classes" on page 474
    # to create documentation.

    # my $house1 = new House("Tom Savage", 250000);
    # Invoking constructor--two ways.
12  my $house1  = House->new("Tom Savage", 250000);
13  my $house2 = House->new("Devin Quigley", 55000);
    # Two objects have been created.
14  $house1->display_object;
15  $house2->display_object;
16  print "$house1, $house2\n";

(Output)
14  Owner: Tom Savage
    Price: 250000
15  Owner: Devin Quigley
    Price: 55000
16  House=HASH(0x9d450), House=HASH(0xa454c)

					  

Explanation

  1. The package House is declared.

  2. The class method new is defined as a constructor.

  3. The first argument to the class method is the name of the class (package).

  4. The instance variables are created from the remainder of the argument list.

  5. The address of an anonymous array is assigned to the reference $ref. The keys are hard coded and the values are supplied from the instance variables.

  6. The "thing" the reference $ref points to is blessed into the class and becomes the new object.

  7. The value of the reference $ref will be returned when the method is called.

  8. The subroutine display_object is an instance method. It is defined in this class.

  9. The first argument to the instance method is the reference to the object.

  10. The while loop is used with the each function to get both keys and values from the hash (object) referenced by $self.

  11. The user of the class loads House.pm into his namespace.

  12. The new method is called with three arguments, House, Tom Savage, and 250000. The first argument is the name of the class. You don't see it, but Perl implictly sends it to the constructor. The next two arguments are sent explicitly by the user of the class. The only request here is that the Owner value is the first argument and the Price value is the second argument. There is no error checking. The example simply shows how to pass arguments to a constructor. The value returned to $house1 is a reference to the hash object.

  13. The new method is called again with different arguments, Devin Quigley and 55000. The value returned to $house2 is a reference to another object. The new method has been used to create two House objects. You can create as many objects as you want. They will all have unique addresses, as shown in the output at line 16. Since the objects were blessed in the constructor, Perl knows that the objects are in the House class.

  14. The instance method is called to display the data for the object referenced by $house1.

  15. The instance method is called again but to display the data of the object referenced by $house2.

  16. The addresses of the two objects are printed.

 

Passing Parameters to Instance Methods

The first argument to an instance method is always a reference to the object. In the called method, this value is typically shifted from the @_ array and stored in a my variable called $self or $this, although it doesn't matter what you call the variable. The remaining arguments are then processed as they are in any regular subroutine.

Example 14.7.

    #!/bin/perl
    # Program to demonstrate passing arguments to an instance method.
    # When method is called, user can select what he wants returned.
1   package House;

2   sub new{     # Constructor, class method
       my $class = shift;
       my ($owner, $salary, $style) = @_;
       my $ref={ "Owner"=>$name,
                 "Price"=>$salary,
                 "Style"=>$style,
               };
       return bless($ref, $class);
    }
3   sub display {           # Instance method
4      my $self = shift;   # Object reference is the first argument
5      foreach $key ( @_){
6         print "$key: $self->{$key}\n";
       }
    }
    1;

--------------------------------------------------------------------

(The Script)
    #!/bin/perl
    # User of the class--Another program
7   use House;
8   my $house = House->new("Tom Savage", 250000, "Cape Cod");
9   $house->display ("Owner", "Style");
                      # Passing arguments to instance method

(Output)
Owner: Tom Savage
Style: Cape Cod

					  

Explanation

  1. The package House is declared. Since this package deals with blessed references and methods, call it a class.

  2. The new method is a constructor. The object is an anonymous hash consisting of three key/value pairs. The key/value pairs are called the properties, or attributes, of the object. The values are passed in as arguments to the constructor. The blessing creates an object. The object, referenced by $ref, is blessed into the House class so Perl can keep track of the package where the object belongs.

  3. The instance method display is defined.

  4. The first argument to the display instance method is a reference to a House object. It is shifted and assigned to $self.

  5. The foreach loop iterates through the remaining arguments in the @_ array, one at a time, assigning each argument in turn to the variable $key. The variable $key is a key in the anonymous array.

  6. The selected values from the associative array are printed.

  7. The user of the class loads the module into his program.

  8. The constructor method is called to create a new House object.

  9. The instance method is called with arguments. The first argument is a pointer to the object, $house, even though you can't see it. The rest of the arguments, provided by the user, are in parentheses.

 

Named Parameters

All of the examples so far have used a House object. In the next example, we will create an Employee object. The Employee constructor will take parameters to be used as properties of an employee. If a constructor method is expecting a name, address, and salary to be passed in that order, it would be easy to send the parameters in the wrong order, causing the address to be assigned to the name, or the name to the salary, and so on. Using named parameters provides a method to ensure that parameters can be passed to a method in any order and still result in the values, getting assigned to the correct attributes. The arguments are passed by the calling, or driver, program as key/value pairs (hash) and received by the constructor as a hash. The following example demonstrates how named parameters are passed to a method and by a method.

The user/driver Program
Example 14.8.

    #!/usr/bin/perl
    # User of Employee.pm--See Example 14.9 for module
1   use Employee;
2   use warnings;
    use strict;
3   my($name, $extension, $address, $basepay, $employee);
4   print "Enter the employee's name. ";
    chomp($name=<STDIN>);
    print "Enter the employee's phone extension. ";
    chomp($extension=<STDIN>);
    print "Enter the employee's address. ";
    chomp($address=<STDIN>);
    print "Enter the employee's basepay. ";
    chomp($basepay=<STDIN>);

    # Passing parameters as a hash
5   $employee = Employee->new( "Name"=>$name,
                               "Address"=>$address,
                               "Extension"=>$extension,
                               "PayCheck"=>$basepay,
                            );
    print "\nThe statistics for $name are: \n";

6   $employee->get_stats;

(Output)
Enter the employee's name. Daniel Savage
Enter the employee's phone extension. 2534
Enter the employee's address. 999 Mission Ave, Somewhere, CA
Enter the employee's basepay. 2200

The statistics for Daniel Savage are:
Address = 999 Mission Ave, Somewhere, CA
PayCheck = 2200
IdNum = Employee Id not provided!
Extension = 2534
Name = Daniel Savage

					  

Explanation

  1. The Employee.pm module will be used by this program.

  2. Warnings will be issued for possible errors, and the strict pragma will track global and undefined variables, barewords, etc.

  3. A list of lexical private variables is created.

  4. The user of the program will be asked for the information that will be passed to the Employee module.

  5. The constructor is called to pass arguments as key/value pairs; that is, a hash is passed to the constructor in the Employee module. (See Example 14.9.) A reference to the object is returned and assigned to $employee.

  6. The instance method get_stats is called to display the employee's attributes.

The Object-Oriented Module
Example 14.9.

    # Module Employee.pm--See Example 14.8 to use this module.
1   package Employee;
2   use Carp;
3   sub new {
4      my $class = shift;
5      my(%params)=@_;   # Receiving the hash that was passed
6      my $objptr={
7          "Name"=>$params{"Name"} || croak("No name assigned"),
           "Extension"=>$params{"Extension"},
8          "Address"=>$params{"Address"},
           "PayCheck"=>$params{"PayCheck"} ||
                   croak("No pay assigned"),
9          ((defined $params{"IdNum"})?("IdNum"=>$params{"IdNum"}):
               ("IdNum"=>"Employee's id was not provided!"
           )),

       };
10     return bless($objptr,$class);
    }
11  sub get_stats{
12     my $self=shift;
13     while( ($key, $value)=each %$self){
          print $key, " = ", $value, "\n";
       }
       print "\n";
    }
    1;

					  

Explanation

  1. The class (package) Employee is declared.

  2. The Carp module from the standard Perl library is used to handle error messages. Instead of using the built-in die function, we can use the croak method from the Carp module to exit when there is an error with a little more detail on what caused the error.

  3. The constructor method new is defined.

  4. The first argument to the constructor method is the name of the class. It is shifted from the @_ array and assigned to $class.

  5. The rest of the arguments in the @_ array are assigned to the hash %params. They were sent to the constructor as a set of key/value pairs.

  6. A reference, $objptr, is assigned the address of an anonymous hash.

  7. The key Name is assigned a value, retrieved from the %params hash. Error checking is done here. If a corresponding value for the key Name is not provided, the croak function will be executed, letting the user know that he did not assign a value to the Name, and the program will exit.

  8. The Address property is assigned by getting its value from the %params hash.

  9. This is an example of how you can make sure the user of the module passed the expected arguments. The conditional statement reads: If the %params has a key called IdNum defined, then get its value and assign it to IdNum; otherwise, when the program runs, tell the user he forgot to include this parameter. In the examples using croak, the program will die if the user doesn't provide input when asked for it, whereas in this form of checking, the program will continue to run.

  10. After assigning properties, a reference to the object is blessed into the class and returned to the caller.

  11. The instance method get_stats is defined.

  12. The first argument is shifted from the @_ array and assigned to $self. It is a pointer to the object.

  13. The while loop is entered. Each key/value pair from the object is returned by the each function and displayed.

 

14.2.8. Polymorphism and Dynamic Binding

Webster's Dictionary defines polymorphism as

polymorphism: n. 1. the state or condition of being polymorphous.[6]

[6] Webster's Encyclopedic Unabridged Dictionary of the English Language, Random House Value Publishing: Avenel, NJ, 1996, p. 1500. Reprinted by permission.

There, that should clear things up! Here's another definition:

Having many forms or the ability to take several forms . . . The same operation may behave differently on different classes.

Polymorphism can be described in many ways, and it's a word that is inherently part of the OO lingo. In Perl, it means that you can provide a method with the same name in different classes and when you call the method, it will do the right thing; in other words, when the reference to the object invokes the method, it will go to the class where the object belongs.

In Example 14.10, polymorphism is demonstrated. Two modules, Cat.pm and Dog.pm, each have three functions with the same names: new, set_attributes, and get_attributes. The driver, or user, program in Example 14.11 will use both of the modules. A reference to the cat or dog object is returned when it's respective class constructors are called. When the access methods are called with an object reference, Perl knows which method to call and to which class it belongs even though the methods have the same name. Perl determines which class the invoking object belongs to and looks in that class (package) for the method being called. The ability to call the right method demonstrates polymorphism. Dynamic, or runtime, binding allows the program to defer calling the correct method until the program is running and, along with polymorphism, to tie the correct method to its associated class without using if statements to determine which method to call. This provides a great deal of flexibility and is necessary for inheritance to work properly.

To take advantage of polymorphism and runtime binding, the object-oriented syntax must be used rather than the :: syntax. If, for example, you have two classes, Director and Rifleman, and both classes contain an access method called shoot, you can write $object–>shoot, and Perl will know which class the object belongs to. It determined the correct class at compile time. In this way, the Director will not shoot bullets at his cast, and the Rifleman will not try to take movies of the rifle range. It is also possible to add another class, such as a BasketballPlayer class, with a different shoot method and be sure that the appropriate method will be called for that class. Without runtime binding and polymorphism, the correct class will be determined based on the outcome of some condition, as shown here:

if ( ref($object1) eq "Director") {
   Director::shoot($object1);
elsif ( ref($object2) eq "Rifleman" ){
   Rifleman::shoot($object2);
else{
   BasketballPlayer::shoot($object3);
}

With the object-oriented syntax, a reference to the object is implicitly passed to the method. Since Perl sends the object to the access method as its first argument and the object has been blessed into the proper class, Perl can implement polymorphism and do the right thing! Assume in Example 14.10 that $object1 was created as an object in the Director class, $object2 object in the Rifleman class, and $object3 in the BasketballPlayer class.

$object1->shoot;evaluates to Director::shoot($object1);
$object2->shoot;evaluates to Rifleman::shoot($object2);
$object3->shoot;evaluates to BasketballPlayer::shoot($object3)

Example 14.10.

( File: Cat.pm)
1   package Cat;
2   sub new{      # Constructor
       my $class=shift;
       my $dptr={};
       bless($dptr, $class);
    }
3   sub set_attributes{            # Access Methods
       my $self= shift;
4      $self->{"Name"}="Sylvester";
       $self->{"Owner"}="Mrs. Black";
       $self->{"Type"}="Siamese";
       $self->{"Sex"}="Male";
    }
5   sub get_attributes{
       my $self = shift;
       print "-" x 20, "\n";
       print "Stats for the Cat\n";
       print "-" x 20, "\n";
       while(($key,$value)=each( %$self)){
          print "$key is $value. \n";
    }
    print "-" x 20, "\n";
    1;
--------------------------------------------------------------------
(File: Dog.pm)
6   package Dog;
7   sub new{               # Constructor
       my $class=shift;
       my $dptr={};
       bless($dptr, $class);
    }
8   sub set_attributes{
       my $self= shift;
9      my($name, $owner, $breed)=@_;
10     $self->{"Name"}="$name";
       $self->{"Owner"}="$owner";
       $self->{"Breed"}="$breed";
    }
11  sub get_attributes{
       my $self = shift;
       print "x" x 20, "\n";
       print "All about $self->{Name}\n";
       while(($key,$value)= each( %$self)){
          print "$key is $value.\n";
       }
       print "x" x 20, "\n";
    }
    1;
--------------------------------------------------------------------

					  

Explanation

  1. This is the package declaration for a class called Cat in module Cat.pm.

  2. The constructor method for the Cat class is called new. A Cat object is blessed into the class.

  3. The access method set_attributes will define data properties of the Cat object.

  4. The object pointer $self is used to assign a key/value pair to give the cat a name.

  5. Another access method, get_attributes, is used to display the Cat object.

  6. In another file, Dog.pm, a package is declared for a class called Dog.

  7. Like the Cat class, the Dog class has a constructor called new. A Dog object is blessed into the class.

  8. The access method set_attributes will define data properties of the Dog object.

  9. The properties of the Dog object are being passed from the driver program and assigned to the @_ array.

  10. The object pointer $self is used to assign a key/value pair to give the dog a name.

  11. Like the Cat class, another access method, get_attributes, is used to display the Dog object.

 

Example 14.11.

(The Script: driver program for Example 14.10)
#!/bin/perl
1   use Cat;   # Use the Cat.pm module
2   use Dog;   # Use the Dog.pm module

3   my $dogref = Dog->new;     # Polymorphism
4   my $catref= Cat->new;

5   $dogref->set_attributes("Rover", "Mr. Jones", "Mutt");
6   $catref->set_attributes;   # Polymorphism

7   $dogref->get_attributes;
8   $catref->get_attributes;

(Output)
xxxxxxxxxxxxxxxxxxxx
All about Rover
Owner is Mr. Jones.
Breed is Mutt.
Name is Rover.
xxxxxxxxxxxxxxxxxxxx
--------------------
Stats for the Cat
--------------------
Sex is Male.
Type is Siamese.
Owner is Mrs. Black.
Name is Sylvester.
--------------------

					  

Explanation

  1. The use directive loads in the Cat.pm module.

  2. The use directive loads in the Dog.pm module. Now we have access to both classes.

  3. The new constructor method is called.[a] The first argument is the name of the class, Dog, which is translated to Dog::new(Dog). A reference to a Dog object is returned. Perl knows the reference belongs to the Dog class because it was blessed in the constructor method. An instance of the Dog class has been created.

    [a] The new constructor could also be called by using the indirect method new Dog.

  4. The new constructor method is called. It passes the name of the class as its first argument. A reference to a Cat object is returned. Perl translates the method call to Cat::new(Cat). Two classes have used the new function, but because Perl knows to which class the method belongs, it always calls the correct version of new. This is an example of polymorphism.

  5. Now that we have a reference to the object, we use it to call the access (instance) methods. Perl translates the $dogref–>set_attributes method to Dog::set_attributes($dogref, "Rover", "Mr. Jones", "Mutt").

  6. This time, the set_attributes method for the cat is called. The Cat class sets the attributes for the cat.

  7. The get_attributes method is called to display the data attributes of the Cat class.

  8. The get_attributes method is called to display the data attributes of the Dog class.

[a] The new constructor could also be called by using the indirect method new Dog.

[a] The new constructor could also be called by using the indirect method new Dog.

The :: versus –> Notation

The –> arrow syntax is used in object-oriented programs that use polymorphism, dynamic binding, and inheritance. The :: syntax is allowed, but it is not flexible and can lead to problems unless conditional statements are used. The following example demonstrates how the :: syntax can be a disadvantage. With the object-oriented syntax, the problem would not occur.

Example 14.12.

    # The Cat class
    package Cat;
    sub new{       # The Cat's constructor
       my $class = shift;
       my $ref = {};
       return bless ($ref, $class);
    }
    sub set_attributes{   # Giving the Cat some attributes,
                          # a name and a voice
       my $self = shift;
       $self->{"Name"} = "Sylvester";
       $self->{"Talk"}= "Meow purrrrrr.... ";
    }
    sub speak {         # Retrieving the Cat's attributes
       my $self = shift;
       print "$self->{Talk} I'm the cat called $self->{Name}.\n";
    }
    1;
---------------------------------------------------------------------
    # The Dog class
    package Dog;   # The Dog's Constructor
    sub new{
       my $class = shift;
       my $ref = {};
       return bless ($ref, $class);
    }
    sub set_attributes{    # Giving the Dog some attributes
       my $self = shift;
       $self->{"Name"} = "Lassie";
       $self->{"Talk"}= "Bow Wow, woof woof.... ";
    }
    sub speak {            # Retrieving the Dog's attributes
       my $self = shift;
       print "$self->{'Talk'} I'm the dog called $self->{'Name'}.\n";
    }
    1;
---------------------------------------------------------------------
    #!/bin/perl
    # User Program
    # This example demonstrates why to use the object-oriented
    # syntax rather than the colon-colon syntax when passing
    # arguments to methods.
    use Cat;
    use Dog;
    $mydog = new Dog;    # Calling the Dog's constructor
    $mycat = new Cat;    # Calling the Cat's constructor

    $mydog->set_attributes;  # Calling the Dog's access methods
    $mycat->set_attributes;  # Calling the Cat's access methods

1   $mydog->speak;
2   $mycat->speak;

3   print "\nNow we make a mistake in passing arguments.\n\n";

4   Cat::speak($mydog); # Perl goes to the Cat class to find the
                          # method, even though attributes have been
                           # set for the dog!

(Output)
1  Bow Wow, woof woof.... I'm the dog called Lassie.
2  Meow purrrrrr.... I'm the cat called Sylvester.

3  Now we make a mistake in passing arguments.

4  Bow Wow, woof woof.... I'm the cat called Lassie.

					  

Explanation

  1. The object-oriented approach of calling the speak method guarantees that Perl will bind the method to the class where it was blessed.

    A reference to the Dog object is passed as the first argument to the speak method. It breaks down to Dog::speak($mydog). Perl determines what class to use at compile time so that when the speak method is called at runtime, it will be bound to the right class.

  2. A reference to the Cat object is passed as the first argument to the speak method. It breaks down to Cat::speak($mydog).

  3. The following line passes a dog reference to the Cat package. This mistake will not occur when using the object-oriented approach, because Perl will be able to determine to which class the method belongs and make the correct method call. This feature is called polymorphism and runtime binding.

  4. By using the :: notation, Perl will figure out the class at runtime and use the speak method found in the Cat class, even though a reference to the Dog object is passed. And we wind up with a cat that barks!

 

14.2.9. Destructors and Garbage Collection

Perl keeps track of the number of references to an object, and when the count reaches 0, the object is automatically destroyed. If a reference goes out of scope or your program exits, Perl handles the garbage collection by destroying every object associated with a reference and deallocating any memory that was used. So, you don't have to worry about cleaning up memory.[7] However, you can define a DESTROY method in your program to get control of the object just before it goes away.

[7] If you use self-referencing data structures, you will be responsible for destroying those references.

Example 14.13.

(The Class)
1 package Employee;
  sub new{
        my $class = shift;
        $ref={};
        bless($ref, $class);
        return $ref;
}

2 sub DESTROY{
        my $self = shift;
3        print "Employee $self->{Name} is being destroyed.\n";
        }

  1;
---------------------------------------------------------------

(The Script)
  #!/usr/bin/perl
  # User of the class
4  use Employee;
5  my $emp1 = Employee->new;  # Create the object
6 { my $emp2 = Employee->new;
    $emp2->{"Name"}="Christian Dobbins";
    print "\t\t$emp2->{'Name'}\n";
  } # Create the object

7  my $emp3 = Employee->new;  # Create the object

8  $emp1->{"Name"}="Dan Savage";
   $emp3->{"Name"}="Willie Rogers";

   print "Here are our remaining employees:\n";
   print "\t\t$emp1->{'Name'}\n";
   print "\t\t$emp3->{'Name'}\n";

(Output)
                 Christian Dobbins
 Employee Christian Dobbins is being destroyed.
 Here are our remaining Employees:
                Dan Savage
                Willie Rogers
 Employee Dan Savage is being destroyed.
 Employee Willie Rogers is being destroyed.

					  

Explanation

  1. The Employee class is declared and its constructor method defined.

  2. When an Employee object is no longer in scope, the DESTROY method is called and this line is printed. The object on line 6 is defined within a block. It goes out of scope when the block exits. The other objects go out of scope when the program ends.

  3. Each time an object goes out of scope, this line is printed.

  4. The Employee module will be used.

  5. A new Employee object, referenced by $emp1, is being created by calling the constructor method.

  6. Another Employee object is created within a block. The object is assigned a "Name" with a value, Christian Dobbins. Since it is a "my" variable, it is lexically scoped, meaning the object will go out of scope when the block is exited, at which time the DESTROY method will be called and remove it from memory.

  7. A third Employee object, referenced by $emp3, is being created by calling the constructor method.

  8. The Employee objects are assigned key/value pairs.

Previous Page Next Page