Object Oriented Perl
Jul. 6th, 2013 10:20 amI started taking a look at object oriented perl the other day. Mostly because I was deconstructing something that didn't work quite right. Anyone a little bit familiar with Perl, will realise that the .. they've probably already seen it, because the in Perl, OO is driven by hashes, references and packages.
(Here's a hint - any time you've used '->' that's probably calling an object, and - because OO lets you encapsulate - there's a lot of that in imported modules).
The basics are - an object is a package, with an internal hash. And ... that's about it.
There's one 'new thing' that you may not have seen - 'bless'. Which is perl's way of giving a generic reference a class. Because they're applicable to objects, you'll see the subroutines within the package referred to as 'methods'.
You 'use' a method, with '->'. This is exactly the same as just running the subroutine, but perl passes the object reference (that you 'blessed') into the subroutine as the first argument.
my $object -> get_value ( "fish" );
Is equivalent to:
&Package::get_value ( $object, "fish" );
You then rely on the 'get_value' sub to 'know what to do' with $object. (Which is one of the underlying principles of OO - you ask it to do something, you don't deal with how it accomplishes it).
By convention too, packages should include a method 'new' - a constructor that sets up the blessed reference, and does any other initialisation that's necessary. (Doesn't have to be called this, but it's usually a good idea). Similarly - 'internal' subroutines are prefixed with _ to indicate they shouldn't be called directly. Unlike stricter languages, perl doesn't enforce privacy within objects. You _can_ diddle with attributes and internal methods, but it's asking for future pain, so don't do it.
If you create a sub called 'DESTROY' then this is called when an object would be deleted (usually due to going out of scope, or on program termination).
That's about it, really. Quite a bare bones implementation. If you want more 'OO' style features, there's a module called Moose, which implements a lot of more advanced features.
Here's some sample, illustrative code:
Code to drive 'MyObject':
(Here's a hint - any time you've used '->' that's probably calling an object, and - because OO lets you encapsulate - there's a lot of that in imported modules).
The basics are - an object is a package, with an internal hash. And ... that's about it.
There's one 'new thing' that you may not have seen - 'bless'. Which is perl's way of giving a generic reference a class. Because they're applicable to objects, you'll see the subroutines within the package referred to as 'methods'.
You 'use' a method, with '->'. This is exactly the same as just running the subroutine, but perl passes the object reference (that you 'blessed') into the subroutine as the first argument.
my $object -> get_value ( "fish" );
Is equivalent to:
&Package::get_value ( $object, "fish" );
You then rely on the 'get_value' sub to 'know what to do' with $object. (Which is one of the underlying principles of OO - you ask it to do something, you don't deal with how it accomplishes it).
By convention too, packages should include a method 'new' - a constructor that sets up the blessed reference, and does any other initialisation that's necessary. (Doesn't have to be called this, but it's usually a good idea). Similarly - 'internal' subroutines are prefixed with _ to indicate they shouldn't be called directly. Unlike stricter languages, perl doesn't enforce privacy within objects. You _can_ diddle with attributes and internal methods, but it's asking for future pain, so don't do it.
If you create a sub called 'DESTROY' then this is called when an object would be deleted (usually due to going out of scope, or on program termination).
That's about it, really. Quite a bare bones implementation. If you want more 'OO' style features, there's a module called Moose, which implements a lot of more advanced features.
Here's some sample, illustrative code:
MyObject.pm:
#!/usr/bin/perl
use strict;
use warnings;
package MyObject;
sub new
{
my ( $class ) = @_;
print "New called\n";
print join ( "\n", @_);
my $self = {};
#need to give self something, because it needs to be
#a reference to something - in this case, an empty hash
#you don't need to do this if you do something like:
#my $self;
#$self -> {_description} = "New Object";
#because if you do that, self is no longer an undefined scalar, it's a reference.
print "And Done\n";
bless ( $self, $class );
#note - the return code of 'bless' is the object reference.
#perl implicitly returns the result of the last operation
#so this 'return' below would occur implicitly if bless were the last
#line in the sub.
return $self;
}
sub print_something
{
my ( $self, @args ) = @_;
print "Printing something (", $self, ") : ", @args, "\n";
}
sub set_description
{
my ( $self, $desc ) = @_;
$self -> {_description} = $desc;
}
sub get_description
{
my ( $self ) = @_;
return $self -> {_description};
}
sub DESTROY
{
print "Tidying up the object\n";
print "Args of:".join ( "\n", @_ ),"\n";
}
1;
Code to drive 'MyObject':
#!/usr/bin/perl
use strict;
use warnings;
use MyObject;
{
my $object_for_me = MyObject -> new();
$object_for_me -> print_something("Cool");
$object_for_me -> set_description ( "New Description" );
print $object_for_me -> get_description, "\n";
print "Doing it 'subroutine style'\n";
&MyObject::set_description ( $object_for_me, "Different Description" );
print &MyObject::get_description ( $object_for_me ),"\n";
}
print "Ending program\n";