Mass Deface
we can start
calling methods on it. This is useful if you want to put object
initialization in its own separate method:
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
$self->_initialize();
return $self;
}
Since the object is also a hash, you can treat it as one, using it to
store data associated with the object. Typically, code inside the class
can treat the hash as an accessible data structure, while code outside
the class should always treat the object as opaque. This is called
B. Encapsulation means that the user of an object does
not have to know how it is implemented. The user simply calls
documented methods on the object.
Note, however, that (unlike most other OO languages) Perl does not
ensure or enforce encapsulation in any way. If you want objects to
actually I opaque you need to arrange for that yourself. This can
be done in a varierty of ways, including using L<"Inside-Out objects">
or modules from CPAN.
=head3 Objects Are Blessed; Variables Are Not
When we bless something, we are not blessing the variable which
contains a reference to that thing, nor are we blessing the reference
that the variable stores; we are blessing the thing that the variable
refers to (sometimes known as the I). This is best
demonstrated with this code:
use Scalar::Util 'blessed';
my $foo = {};
my $bar = $foo;
bless $foo, 'Class';
print blessed( $bar ); # prints "Class"
$bar = "some other value";
print blessed( $bar ); # prints undef
When we call C on a variable, we are actually blessing the
underlying data structure that the variable refers to. We are not
blessing the reference itself, nor the variable that contains that
reference. That's why the second call to C returns
false. At that point C<$bar> is no longer storing a reference to an
object.
You will sometimes see older books or documentation mention "blessing a
reference" or describe an object as a "blessed reference", but this is
incorrect. It isn't the reference that is blessed as an object; it's
the thing the reference refers to (i.e. the referent).
=head2 A Class is Simply a Package
X X X<@ISA> X
Perl does not provide any special syntax for class definitions. A
package is simply a namespace containing variables and subroutines. The
only difference is that in a class, the subroutines may expect a
reference to an object or the name of a class as the first argument.
This is purely a matter of convention, so a class may contain both
methods and subroutines which I operate on an object or class.
Each package contains a special array called C<@ISA>. The C<@ISA> array
contains a list of that class's parent classes, if any. This array is
examined when Perl does method resolution, which we will cover later.
It is possible to manually set C<@ISA>, and you may see this in older
Perl code. Much older code also uses the L pragma. For new code,
we recommend that you use the L pragma to declare your parents.
This pragma will take care of setting C<@ISA>. It will also load the
parent classes and make sure that the package doesn't inherit from
itself.
However the parent classes are set, the package's C<@ISA> variable will
contain a list of those parents. This is simply a list of scalars, each
of which is a string that corresponds to a package name.
All classes inherit from the L class implicitly. The
L class is implemented by the Perl core, and provides
several default methods, such as C, C, and C.
The C class will I appear in a package's C<@ISA>
variable.
Perl I provides method inheritance as a built-in feature.
Attribute inheritance is left up the class to implement. See the
L section for details.
=head2 A Method is Simply a Subroutine
X
Perl does not provide any special syntax for defining a method. A
method is simply a regular subroutine, and is declared with C.
What makes a method special is that it expects to receive either an
object or a class name as its first argument.
Perl I provide special syntax for method invocation, the C<< ->
>> operator. We will cover this in more detail later.
Most methods you write will expect to operate on objects:
sub save {
my $self = shift;
open my $fh, '>', $self->path() or die $!;
print {$fh} $self->data() or die $!;
close $fh or die $!;
}
=head2 Method Invocation
X X X X<< -> >>
Calling a method on an object is written as C<< $object->method >>.
The left hand side of the method invocation (or arrow) operator is the
object (or class name), and the right hand side is the method name.
my $pod = File->new( 'perlobj.pod', $data );
$pod->save();
The C<< -> >> syntax is also used when dereferencing a reference. It
looks like the same operator, but these are two different operations.
When you call a method, the thing on the left side of the arrow is
passed as the first argument to the method. That means when we call C<<
Critter->new() >>, the C method receives the string C<"Critter">
as its first argument. When we call C<< $fred->speak() >>, the C<$fred>
variable is passed as the first argument to C.
Just as with any Perl subroutine, all of the arguments passed in C<@_>
are aliases to the original argument. This includes the object itself.
If you assign directly to C<$_[0]> you will change the contents of the
variable that holds the reference to the object. We recommend that you
don't do this unless you know exactly what you're doing.
Perl knows what package the method is in by looking at the left side of
the arrow. If the left hand side is a package name, it looks for the
method in that package. If the left hand side is an object, then Perl
looks for the method in the package that the object has been blessed
into.
If the left hand side is neither a package name nor an object, then the
method call will cause an error, but see the section on L for more nuances.
=head2 Inheritance
X
We already talked about the special C<@ISA> array and the L
pragma.
When a class inherits from another class, any methods defined in the
parent class are available to the child class. If you attempt to call a
method on an object that isn't defined in its own class, Perl will also
look for that method in any parent classes it may have.
package File::MP3;
use parent 'File'; # sets @File::MP3::ISA = ('File');
my $mp3 = File::MP3->new( 'Andvari.mp3', $data );
$mp3->save();
Since we didn't define a C method in the C class,
Perl will look at the C class's parent classes to find the
C method. If Perl cannot find a C method anywhere in
the inheritance hierarchy, it will die.
In this case, it finds a C method in the C class. Note
that the object passed to C in this case is still a
C object, even though the method is found in the C
class.
We can override a parent's method in a child class. When we do so, we
can still call the parent class's method with the C
pseudo-class.
sub save {
my $self = shift;
say 'Prepare to rock';
$self->SUPER::save();
}
The C modifier can I be used for method calls. You can't
use it for regular subroutine calls or class methods:
SUPER::save($thing); # FAIL: looks for save() sub in package SUPER
SUPER->save($thing); # FAIL: looks for save() method in class
# SUPER
$thing->SUPER::save(); # Okay: looks for save() method in parent
# classes
=head3 How SUPER is Resolved
X
The C pseudo-class is resolved from the package where the call
is made. It is I resolved based on the object's class. This is
important, because it lets methods at different levels within a deep
inheritance hierarchy each correctly call their respective parent
methods.
package A;
sub new {
return bless {}, shift;
}
sub speak {
my $self = shift;
$self->SUPER::speak();
say 'A';
}
package B;
use parent 'A';
sub speak {
my $self = shift;
$self->SUPER::speak();
say 'B';
}
package C;
use parent 'B';
sub speak {
my $self = shift;
$self->SUPER::speak();
say 'C';
}
my $c = C->new();
$c->speak();
In this example, we will get the following output:
A
B
C
This demonstrates how C is resolved. Even though the object is
blessed into the C class, the C method in the C class
can still call C and expect it to correctly look in the
parent class of C (i.e the class the method call is in), not in the
parent class of C (i.e. the class the object belongs to).
There are rare cases where this package-based resolution can be a
problem. If you copy a subroutine from one package to another, C
resolution will be done based on the original package.
=head3 Multiple Inheritance
X
Multiple inheritance often indicates a design problem, but Perl always
gives you enough rope to hang yourself with if you ask for it.
To declare multiple parents, you simply need to pass multiple class
names to C