Object Oriented Perl
Jul. 6th, 2013 10:20 am![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
I 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";