Professional Documents
Culture Documents
● Encapsulation
● Aggregation
● Abstraction
Skip definitions
Classes
● Templates for defining objects state and
behavior
Encapsulation
package Car;
sub new {
my $class = shift;
my $brand = shift;
my $self = {};
$self->{'brand'} = $brand;
bless ($self, $class);
return $self;
}
What OOP features offers Perl?
● Encapsulation – in general only by convention.
● Some tricks: private variable, private method, private function
●
“Inside-out” classes not handy... “There is only one way to do it...” .
What OOP features offers Perl?
{
{ package Mom;
package Mom; (...)
(...)
sub _prepare_pastry{
my $_prepare_pastry = sub{ if (caller ne __PACKAGE__){
print "makin' pastry 2 \n"; die;
}; }
else {
sub make_cookies{ print "makin' pastry \n";
&{$_pastry}; }
print "cookies ready\n"; }
}
}
sub make_cookies{
_prepare_pastry();
package main;
print "cookies ready\n";
(...)
}
package main;
}
my $mom = Mom->new();
package main;
$mom->make_cookies();
(...)
my $mom = Mom->new();
$mom->_prepare_pastry(); #this
compiles!
$mom->make_cookies();
What OOP features offers Perl?
● Aggregation
sub cars {
my $self = shift;
my $car = shift;
if ( ref( $car ) eq 'Car' ) {
push @{ $self->{'cars'} }, $car;
}
return $self->cars;
}
What OOP features offers Perl?
● Inheritance (multi-object) and polymorphism: use base()
sub load{
croak('not implemented');
}
package BMP;
use base qw(File);
package JPG;
use base qw(File);
sub load{
my $self = shift;
print "File loaded. \n";
}
What OOP features offers Perl?
What is missing?
● The in-language support for OO features is minimal.
● No type checking, no horizontal inheritance, no encapsulation...
Moose =
Class::MOP + semantic
Moose is Perl.
● Type matching
● Coercion - the ability to convert types of one type to another when
necessary
● Encapsulation
● Method Modifiers - the ability to add code that runs before, after or
around an existing method
● Horizontal inheritance - roles - the ability to add predefined
functionality to classes without sub-classing
sub goto{
my $self = shift; Class methods.
my $place_name = shift;
print "Going to $place_name \n";
}
__PACKAGE__->meta->make_immutable;
no Moose;
1;
$acar->RegNum('123456');
print $acar->RegNum;
We get also default
$acar->goto('Oriente');
accessors for free.
Moose – first example.
12 lines of code from previous slide give us all this:
package Vehicle;
use strict;
sub new {
my $class = shift;
my %args = @_;
1;
Lets have a closer look...
● Arguments
'RegNum'=>'1234'
);
We can still read it wherever we want.
print $avehicle->RegNum."\n";
What more we can do with attributes?
● Required arguments
Required attribute must be set.
It means that...
has 'RegNum' => (
'is' => 'ro',
'isa' => 'Str',
'required' => 1,
);
… this will not compile
#$acar = Vehicule->new();
print $avehicle->RegNum;
$avehicle->unregister();
subtype 'RegistrationNo'
=> as 'Str', parent type
=> where { /^(\d\d)(-)(\w\w)(-)(\d\d)$/ },
=> message {"$_ is not valid registration number."};
package MyTypes;
what we want to create
use Moose;
use MooseX::Types -declare => [qw(Coordinate Point)];
use MooseX::Types::Moose qw(Int HashRef);
what we use to create
subtype Point,
as Int, a point
where { $_>= 0},
message {'Must be positive number.'};
This is very useful type. We can pack it in separate package and reuse later.
One Step Further - MooseX.
●Custom types
Lets use the coordinate to define where is the vehicle.
(...)
has 'place' => ( modify the vehicle class
'is' => 'rw',
'isa' => Coordinate,
(Vehicle.pm)
);
(...)
$avehicle->place( $place );
package MyTypes;
use Moose;
use MooseX::Types -declare => [qw(Coordinate Point)];
use MooseX::Types::Moose qw(Int HashRef ArrayRef);
subtype Point,
as Int,
(...)
where { $_> 0}, has 'place' => (
message {'Must be positive number.'}; 'is' => 'rw',
'isa' => Coordinate,
'coerce' => 1,
subtype Coordinate,
);
as HashRef,
where { Point->check( $_->{'X'} ) and Point->check( $_->{'Y'} )},
message {'Incorect coordinate.'.$_ }; (...)
coerce Coordinate,
from ArrayRef,
via {
{'X'=>$_->[0], 'Y'=>$_->[1]}
};
We define how we can
transform one type to another.
1;
Private attributes – only convention.
The vehicle may change its place only when it moves ?
(...)
$avehicle->goto([7,8]);
print Dumper($avehicle);
print 'The vehicle is at'.$avehicle->_place->{'X'}.','.$avehicle->_place-
>{'Y'}.'.';
my $coordinate2 = $self->_place;
my $x2 = $coordinate2->{'X'};
Accessing modified
my $y2 = $coordinate2->{'Y'}; attributes
my $distance = sqrt(($x1-$x2)**2+($y1-$y2)**2);
print $avehicle->_mileage;
Every time we move vehicle
$avehicle->goto([7,8]);
$avehicle->goto([1,1]); the mileage increase.
$avehicle->goto([4,5]);
print $avehicle->_mileage
Lazy, lazy_build and trigger.
Imagine we want to sell the vehicle. The price depends on the mileage.
$avehicle->goto([1,1]);
...despite we move, the price didn't change.
print $avehicle->price;
Lazy build calculates the value only if it is unset.
$avehicle->goto([4,5]); Therefore we need to clean it every time
we want to get updated value.
print $avehicle->price;
Lazy, lazy_build and trigger.
Let's run the clearer automatically.
package Car;
use Moose;
Parent class
extends 'Vehicle';
sub refuel {
my $self = shift;
$self->fuel($self->fuel + 10); New method
}
no Moose
Code reuse - inheritance in Moose.
package Bike;
use Moose;
extends 'Vehicle';
● Role is not a class – can't be subclassed, can't be extended … we can't create an object of a role .
● But we can use a role in a class, and methods of the role in an object.
Better code reuse – inheritance and roles.
We can create a 'truck' role and use it in our vehicle.
The only difference
extends 'Car';
with 'Truck';
Lorry = Car with Truck role
no Moose;
1;
use Lorry;
(…)
Lorry has a Truck role – mast have capacity.
$alorry->do_load(40);
#$alorry->do_load(40); #unsecessfull - is loaded
We can use all truck functions.
$alorry->do_unload();
$alorry->do_load(30);
package Truck;
use Moose::Role;
We require that a method 'fuel'
requires 'fuel'; is present in a class where we
use the Truck role.
(…)
use Moose;
extends 'Bike';
with 'Truck';
$acar = Vehicule->new('11-xx-11');
my %a = @_;
my %args = ();
if ( @_ == 1 ) {
$args{ 'RegNum' } = $_[0];
return $class->$orig( %args );
}
return $class->$orig( %a );
};
BUILDARGS and BUILD
There is a possibility to have a bike without registration. But we want to be warn about it...
my $abike = Bike->new();
my $abike2 = Bike->new('22-yy-66');
Aggregation and Native Traits
Let's create a garage for our vehicles.
no Moose;
1;
Defining accessors.
(these accessors use type checking).
More native traits:
Array: push, pop, shift, unshit, map, sort, grep …
Hash: get, set, delete, exists, defined, clear, is_empty …
String: append, substr, length...
Bool: set, unset, toggle...
Code: execute, execute_method...
Aggregation and Native Traits
Let's park some vehicles...
my $garage = Garage->new();
$garage->add_vehicle($avehicle);
my $v = $garage->get_vehicle();
$garage->add_vehicle($acar);
my $acar2 = $garage->get_vehicle();
For example:
● http://www.oscon.com/oscon2010/public/schedule/detail/13673
Moose is Perl: A Guide to the New Revolution
http://www.slideshare.net/dtreder/moose-527243
●
Awesome presentation with huge dose of humor, but also very helpful.
http://search.cpan.org/~drolsky/Moose-1.21/
●