SlideShare a Scribd company logo
1 of 47
Download to read offline
Moose
OOP for Perl.
What we expect from OOP

●    Classes (methods, types, attributes, open recursion...)

●    Encapsulation

●    Aggregation

●    Message passing and dynamic dispatch

●    Inheritance and polymorphism

●    Abstraction


    Skip definitions
Classes
●   Templates for defining objects state and
    behavior
Encapsulation

●   Specifying which classes may use the
    members of an object e.g:

    public, protected or private, determining
    whether they are available to all classes,
    sub-classes or only the defining class.
Aggregation

●   Object containing another object
Message passing and dynamic dispatch

●   Message passing is the process by which an object sends data to
    another object or asks the other object to invoke a method

●   when a method is invoked on an object, the object itself determines
    what code gets executed by looking up the method at run time in a
    table associated with the object (needed when multiple classes
    contain different implementations of the same method )
Inheritance and polymorphism
●   allows the programmer to treat derived class members just like
    their parent class's members ("Subclasses" are more specialized
    versions of a class, which inherit attributes and behaviors from
    their parent classes, and can introduce their own.)

●   a class has all the state and behavior of another class -
    polymorphism
What OOP features offers Perl?
●   MOP in Perl5:
    ●   Class - package

    ●   Object - blessed reference (a scalar type holding a reference to object
        data – object may be a hash, array, or reference to subroutine.)

    ●   Method - a subroutine within a package

    ●   Constructor – a method that returns reference to blessed variable
What OOP features offers Perl?

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

     package Mom;                                  package Kido;

        sub new{                                   use base qw(Mom);
            my $class = shift;
            my $self = {                           sub ask_for_pin{
                'CARD_PIN' => '0000',                  my $self = shift;
                };                                     my $how = shift;
                                                       return &{$self}($how);
             my $closure = sub {                   }
                 my $arg = shift;
                 if ($arg and $arg eq 'nice'){
                     return $self->{'CARD_PIN'};   package main;
                     }                             my $mom = Mom->new();
                 else {                            my $kido = Kido->new();
                     return 'forget!';
                     }                             print $kido->ask_for_pin('not nice');
                 };                                print $kido->ask_for_pin('nice');
             bless($closure, $class);
             return $closure;
        };




●
    “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 readyn";          }
        }
}
                                          sub make_cookies{
                                             _prepare_pastry();
package main;
                                             print "cookies readyn";
(...)
                                             }
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


    package Person;                         my $eva = Person->new();
                                            my $car1 = Car->new();
     sub new {                              $car1->brand( 'Fiat' );
       my $class = shift;
       my $self = {};                       $eva->cars->[0]->brand(); #returns 'Fiat'
       $self->{'cars'} = ();
       bless( $self, $class );
       return $self;
     }

     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()

package Person;                                     package Employee;

sub new {                                           use base qw(Person);
        my $class = shift;
        my $self = {};                              sub new {
                                                      my $class = shift;
        bless( $self, $class );                       my $job   = shift;
        return $self;                                 my $self = $class->SUPER::new();
}                                                     $self->{'job'} = $job;

sub name {                                              bless( $self, $class );
  my $self = shift;                                     return $self;
  if ( @_ ) { $self->{'name'} = shift }             }
  return $self->{'name'};
}                                                   #overriding
                                                    sub say_name {
sub say_name {                                        my $self = shift;
  my $self = shift;                                   $self->SUPER::say_name();
  printf( "My name is %s. n", $self->{'name'} );     printf( "My job is %s.n", $self->{'job'} );
}                                                     }

                                                    #inheritance and polymorphism
                                                    my $adam = Employee->new( 'Developer' );
                                                    $adam->name( 'Adam' );
                                                    $adam->say_name
What OOP features offers Perl?
●   Abstraction – only objects
    package File;                           my $bmp = BMP->new();
      use Carp;                             $bmp->load();

      sub new {                             my $jpg = JPG->new();
        my $class = shift;                  $jpg->load();
        my $self = {};
        bless ($self, $class);
        return $self;
      }

      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...




              There is more than one way to do it!
Moose




There is more than one way to do it, but sometimes
       consistency is not a bad thing either!
Moose is Perl.




       Moose =
Class::MOP + semantic
Moose is Perl.

●   common system for building classes
●   new levels of code reuse, allowing you to improve your
code with features that would otherwise be too complex or
expensive to implement
Moose is Perl.
Everything missing in OO Perl you can find in Moose + some
important bonuses!

  ●   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


… and much more.
Moose – first example.
                                                              Sets strict and warnings
              package Vehicle;
              use Moose;
MOOSE CLASS




              has 'RegNum' => (                                   Class attributes.
                      'is' => 'rw',
                      'isa' => 'Str');

              sub goto{
                  my $self = shift;                                Class methods.
                  my $place_name = shift;
                  print "Going to $place_name n";
                  }

              __PACKAGE__->meta->make_immutable;

              no Moose;
              1;




              use Vehicle;                                   We get new() for free
              my $avehicle = Vehicle->new();

              $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 = @_;

      my $self   = { '_RegNum' => undef };

      if ( exists( $args{'RegNum'} ) && defined( $args{'RegNum'} ) ) {
          $self->{'_RegNum'} = $args{'RegNum'};
      }

      return bless($self, $class);
 }                                                                       package Vehicle;
                                                                         use Moose;
 sub RegNum {
     my $self   = shift;                                                 has 'RegNum' => (
     my $regnum = shift;                                                         'is' => 'rw',
     if ( $regnum ) {                                                            'isa' => 'Str');
         $self->{'_RegNum'} = $regnum;
     }                                                                   sub goto{
     return $self->{'_RegNum'};                                              my $self = shift;
 }                                                                           my $place_name = shift;
                                                                             print "Going to $place_name n";
 sub goto{                                                                   }
     my $self = shift;
     my $place_name = shift;                                             no Moose;
     print "Going to $place_name n";                                    1;
 }

 1;
Lets have a closer look...
●   Arguments


    (...)                                  'rw' or 'ro' – tells which accessors will be created

    has 'RegNum' => (
            'is' => 'rw',
            'isa' => 'Str'
    );
                                                              Moose types:
    (...)
                                                  Bool, Str, Num, Int, ArrayRef, HashRef,
                                                                and more




'is' – defines if argument is read-write or read-only
'isa' – defines type of the attribute (and validate it during assignment)
Lets have a closer look...
●   Read- only arguments

    has 'RegNum' => (                      If we restrict access to the attribute...
            'is' => 'ro',                 the default accessor won't be created.
            'isa' => 'Str'
    );

                                                 This method doesn't exist
    $avehicle->RegNum('123456');              – it results in compilation error



                                          The only right moment to set up the
    my $avehicle = Vehicle->new(            attribute is during initialization.

         '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();


my $avehicle = Vehicle->new('RegNum'=>'123456');   ...but we still can have illegal vehicle..
                                                     RegNum can be set to empty string.
my $avehicle = Vehicle->new('RegNum'=>'');




has 'RegNum' => (
        'is' => 'ro',
        'required' => 1,
        );
                                                                      BUT
my $avehicle = Vehicle->new('RegNum'=>undef);
                                                      If attribute has no type it can be
                                                               set to undefined
What more we can do with attributes?
●Clearer and predicate
Imagine... the vehicle is a broken and is waiting to be scraped, but first you must unregister it .


has 'RegNum' => (
        'is' => 'ro',                                   You can't use accessors because it is “ro”.
        'isa' => 'Str',
        'required'=> 1,
        'clearer' => 'unregister',
                                                       but... you can set clearer to clean the value
        'predicate'=>'is_registered',
        );

                                                             and predicate to check if the
                                                                     value exists
my $avehicle = Vehicule->new('RegNum'=>'1234');

print $avehicle->RegNum;

$avehicle->unregister();

if (!$avehicle->is_registered()){                                The method you get for free.
    print "Vehicle illegal!.n";
    }
What more we can do with attributes?
 ●   Subtypes
Not every string can be the registration number...

 package Vehicle;                                                use TypeConstraints
 use Moose;                                                       and create subtype
 use Moose::Util::TypeConstraints;

 subtype 'RegistrationNo'
         => as 'Str',                                                       parent type
         => where { /^(dd)(-)(ww)(-)(dd)$/ },
         => message {"$_ is not valid registration number."};


 has 'RegNum' => (                                              compare $_ to something
         'is' => 'ro',
         'isa' => 'RegistrationNo',
         'required'=> 1,
         'clearer' => 'unregister',                                     and use it
         'predicate'=>'is_registered',
         );



my $avehicle = Vehicle->new('RegNum'=>'11-xx-22');               Subtypes can be more complex
                                                                      more examples here
#my $avehicle = Vehicle->new('RegNum'=>'111-xx-22');
One Step Further - MooseX.
  ●   Custom types
Lets define where is our vehicle.... a 2D coordinate - two points: x and y that
must have positive value.


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.'};


                                                    A coordinate that is a has of two valid points
subtype Coordinate,
    as HashRef,
    where { Point->check( $_->{'X'} ) and Point->check( $_->{'Y'} )},
    message {'Incorect coordinate.'.$_ };



 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.

 use MyTypes qw( Coordinate );
                                                             import custom type

 (...)
 has 'place' => (                                          modify the vehicle class
     'is' => 'rw',
     'isa' => Coordinate,
                                                                (Vehicle.pm)
 );
 (...)




 my $place = {'X'=>1, 'Y'=>3 };

 $avehicle->place( $place );

                                                          use it where ever you need
One Step Further - MooseX.
 ●   Custom types and coercion
                                                                           In the end, in class definition,
But maybe it would be easier to use it this way...?                         Don't forget to turn on the
                                                                             coercion on the argument
 $avehicle->place( [4,5] );

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 ?

(...)                                                                    This is what the manual says
#an attribute to be publicly readable, but only privately settable.     – but this is only CONVENTION.
has '_place' => (
    'is' => 'ro',
    'isa' => Coordinate,
    'coerce' => 1,
    'writer' => '_set_place',
      );                                                              reader and writer redefine the
                                                                        names of custom accessors
sub goto{
    my $self = shift;
    my $coordinate = shift;
    $self->_set_place($coordinate);
}                                                                 Now we can “move” the vehicle.

(...)

$avehicle->goto([7,8]);
print Dumper($avehicle);
print 'The vehicle is at'.$avehicle->_place->{'X'}.','.$avehicle->_place-
>{'Y'}.'.';

#my $place = {'X'=>1, 'Y'=>3 };                                        However this still would work.
#my $other_place = [4,5];                                                   MOOSE is PERL
#$avehicle->_set_place( $place );
Method modifiers
Mileage – every time the vehicle moves its mileage increase.

 has '_mileage' => (                                                              One more
         'is' => 'ro',
         'isa' => 'Num',
                                                                               private attribute.
         'required' => 1,
         'default' => 0,
         'writer' => '_set_mileage',
         );                                               Method modifier


                                                                              Has access to attributes,
 around 'goto' => sub {                                                     before they are modified by
     my $orig = shift;
     my $self = shift;                                                                method
      my $coordinate1 = $self->_place;
      my $x1 = $coordinate1->{'X'};
      my $y1 = $coordinate1->{'Y'};
                                                               Executing main method
      #@_ stores new coordinate
      $self->$orig(@_);

      my $coordinate2 = $self->_place;
      my $x2 = $coordinate2->{'X'};
                                                                              Accessing modified
      my $y2 = $coordinate2->{'Y'};                                               attributes
      my $distance = sqrt(($x1-$x2)**2+($y1-$y2)**2);

      $self->_set_mileage($self->_mileage + $distance);                                      other actions
 };
Method modifiers
Mileage – every time the vehicle moves its mileage increase.




                                                   Define default value
  has '_place' => (
      'is' => 'ro',
      'isa' => Coordinate,
      'coerce' => 1,
      'writer' => '_set_place',
      'default' => sub {[0,0]},
      );




  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.

                                                          Lazy - value is calculated only when
    has 'price' => (
            'is' => 'ro',                                      it is accessed and is unset.
            'isa' => 'Num',
            'predicate'=>'has_price',
            'lazy_build'=>1,
            'builder'=>'calculate_price',                          lazy + clearer = lazy_build
            'init_arg'=>undef,
            );


    sub calculate_price {                                  Lazy needs default value or builder
        my $self = shift;
        my $price = 100000;
        if ($self->_mileage != 0){
            $price = $price / $self->_mileage;
        }
        return $price;                                           Method building the value.
    }



    $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.

 has '_mileage' => (
                                                               Every time the mileage changes the
         'is' => 'ro',                                         clearer for price attribute is triggered.
         'isa' => 'Num',
         'required' => 1,
         'default' => 0,
         'writer' => '_set_mileage',
         'trigger' => sub {
             my $self=shift;
                                                         After this change the previous example
             $self->clear_price;                       shows updated value every time we access it
             }
         );


Lazy build is very useful for attributes are expensive to calculate –
we calculate it only while reading.
 sub sell_vehicle {
     my $self = shift;
     $self->clear_price;
     return $self->price;                               We can also use method instead the trigger.
     }
                                                         The price is updated every time we read it
 $avehicle->goto([1,1]);                                              using the method.
 print $avehicle->price;
                                                              Useful for expensive calculation.
 $avehicle->goto([4,5]);
 print $avehicle->price;

 print "The final price: ".$avehicle->sell_vehicle. "n";
Code reuse - inheritance in Moose.
Is the vehicle car or bike?

package Car;
use Moose;
                                                   Parent class
extends 'Vehicle';

has 'fuel' =>(
    'is' => 'rw',
    'isa' => 'Int',
    'default'=>0,                             New attribute
);

sub refuel {
    my $self = shift;
    $self->fuel($self->fuel + 10);              New method
    }

override goto => sub{
    my $self = shift;
                                            Overwritten method
     if($self->fuel eq 0){
         print 'No fuel';
         return;
     }
     return super;
};
                                                    Calling super

no Moose
Code reuse - inheritance in Moose.


package Bike;
use Moose;

extends 'Vehicle';

has '+RegNum' => (
    'required'=> 0,
    );                              changing inherited attribute
no Moose;
1;




my $abike = Bike->new();   registration number is not linger required
Better code reuse – inheritance and roles.
Short explanation:

●   Role is a “state or behavior that can be shared between classes.”

●   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


     package Truck;                           sub do_load {
     use Moose::Role;                             my $self = shift;
                                                  my $load = shift;
     has 'capacity' => (
         'is' => 'ro',                            if(($self->capacity >= $load) and !$self->load){
         'isa' => 'Int',                            $self->load(1);
         'default'=>10,                           }else{
         'required'=>1,                             print 'Load unsuccessful,';
     );                                           }
                                              }

     has 'load' => (                          sub do_unload {
         'is' => 'rw',                            my $self = shift;
         'isa' => 'Bool',                         my $load = shift;
         'default'=>0,
     );                                           if($self->load){
                                                    $self->load(0);
                                                  }else{
                                                    print 'Nothing to unload,';
                                                  }
                                              }
We create a piece of functionality            no Moose;
                                              1;
exactly the same way as we were
     creating a moose class.
Better code reuse – inheritance and roles.
We want to have a car with a “truck functionality” - a lorry.
 package Lorry;
 use Moose;

 extends 'Car';
 with 'Truck';
                                                                  Lorry = Car with Truck role

 no Moose;
 1;


 How to use Lorry?                           Lorry is a vehicle – mast have registration number.
 (…)

 use Lorry;

 (…)
                                                            Lorry has a Truck role – mast have capacity.


 my $alorry = Lorry->new('RegNum'=>'11-xx-23', 'capacity'=>50);
 #$alorry->do_load(100); - more than 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);

 #$alorry->goto([2,4]); - still can't go without the fuel
                                                                              But Lorry is still a car
                                                                             so won't go without fuel.
Better code reuse – inheritance and roles.
In the end we want to assure that the truck role will be only used with anything that uses fuel
(Have you ever seen a lorry-bike?)

  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';

  no Moose;                                                   Since bike doesn't use fuel
                                                              this code will not compile.



  'Truck' requires the method 'fuel' to be implemented by 'Lorrybike' at
  /usr/local/lib/perl5/site_perl/5.10.0/i386-linux-thread-multi/Moose/Meta/Role/Application.pm line 51
        Moose::Meta::Role::Application::apply('Moose::Meta::Role::Application::ToClass=HASH(0xa5faa2c)',
  'Moose::Meta::Role=HASH(0xa5f6a6c)', 'Moose::Meta::Class=HASH(0xa5f8754)') called at
  /usr/local/lib/perl5/site_perl/5.10.0/i386-linux-thread-multi/Moose/Meta/Role/Application/ToClass.pm
  line 31
  (...)
BUILDARGS and BUILD
Let's go back to Vehicle. It would be awesome to create a vehicle this way :

 $acar = Vehicule->new('11-xx-11');




                                                 BUILDARGS method is called as a class method
 around BUILDARGS => sub {
                                                 before an object is created. It has direct access
     my $orig = shift;                                to arguments passed in method call.
     my $class = shift;

      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...




                                                 BUILD method is called after an object is created.
   sub BUILD {
       my $self = shift;
           if(!$self->RegNum){
               if($self->isa('Bike')){
                   print "Vehicle without registration number.n";
                   }
               }
       }
                                                              We will be warn about creating a
                                                             bike without a registration number.



   my $abike = Bike->new();
   my $abike2 = Bike->new('22-yy-66');
Aggregation and Native Traits
Let's create a garage for our vehicles.


  package Garage;                                                    Notice: there is no
  use Moose;
  use Moose::Util::TypeConstraints;                                      'is' =>'ro|rw'


  has 'vehicles' => (
      'isa'=> 'ArrayRef[ Vehicle ]',
      'default' => sub {[]},
      'traits' => ['Array'],
      'handles'=> {
                                                               Trait – a role added to attribute.
          'add_vehicle' => 'push',                           Here we make the vehicles attribute
          'get_vehicle' => 'shift',                                    work as an array.
          },
  );

  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();




                                         $acar2 and $acar is the same
                                        (reference to the same object)
What more you can do in Moose?

For example:

●   Delegation - "proxy" methods call some other method on an
    attribute.

●   Custom traits - MooseX

●   Custom OO system – sub-classing methaclasses

●   And much more...
Some tips
●   If you don't know what is wrong try to load package from command line :

                       perl -Ilib/ -e 'use Coordinate'

●   $object->dump for debugging
More information:

●   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/
●


Moose::Manual and Moose::Cookbook

More Related Content

What's hot

WordCamp Portland 2018: PHP for WordPress
WordCamp Portland 2018: PHP for WordPressWordCamp Portland 2018: PHP for WordPress
WordCamp Portland 2018: PHP for WordPressAlena Holligan
 
(Parameterized) Roles
(Parameterized) Roles(Parameterized) Roles
(Parameterized) Rolessartak
 
WordPress Cuztom Helper
WordPress Cuztom HelperWordPress Cuztom Helper
WordPress Cuztom Helperslicejack
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsMichael Pirnat
 
Descobrindo a linguagem Perl
Descobrindo a linguagem PerlDescobrindo a linguagem Perl
Descobrindo a linguagem Perlgarux
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix itRafael Dohms
 
Synapseindia object oriented programming in php
Synapseindia object oriented programming in phpSynapseindia object oriented programming in php
Synapseindia object oriented programming in phpSynapseindiappsdevelopment
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksNate Abele
 
Shortcodes In-Depth
Shortcodes In-DepthShortcodes In-Depth
Shortcodes In-DepthMicah Wood
 
Object Oriented PHP5
Object Oriented PHP5Object Oriented PHP5
Object Oriented PHP5Jason Austin
 
WordPress London 16 May 2012 - You don’t know query
WordPress London 16 May 2012 - You don’t know queryWordPress London 16 May 2012 - You don’t know query
WordPress London 16 May 2012 - You don’t know queryl3rady
 
Bioinformatics p5-bioperl v2013-wim_vancriekinge
Bioinformatics p5-bioperl v2013-wim_vancriekingeBioinformatics p5-bioperl v2013-wim_vancriekinge
Bioinformatics p5-bioperl v2013-wim_vancriekingeProf. Wim Van Criekinge
 
Your code sucks, let's fix it! - php|tek13
Your code sucks, let's fix it! - php|tek13Your code sucks, let's fix it! - php|tek13
Your code sucks, let's fix it! - php|tek13Rafael Dohms
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix itRafael Dohms
 
Coffeescript: No really, it's just Javascript
Coffeescript: No really, it's just JavascriptCoffeescript: No really, it's just Javascript
Coffeescript: No really, it's just JavascriptBrian Mann
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of LithiumNate Abele
 

What's hot (20)

Coffee Script
Coffee ScriptCoffee Script
Coffee Script
 
WordCamp Portland 2018: PHP for WordPress
WordCamp Portland 2018: PHP for WordPressWordCamp Portland 2018: PHP for WordPress
WordCamp Portland 2018: PHP for WordPress
 
(Parameterized) Roles
(Parameterized) Roles(Parameterized) Roles
(Parameterized) Roles
 
The jQuery Divide
The jQuery DivideThe jQuery Divide
The jQuery Divide
 
WordPress Cuztom Helper
WordPress Cuztom HelperWordPress Cuztom Helper
WordPress Cuztom Helper
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
 
Descobrindo a linguagem Perl
Descobrindo a linguagem PerlDescobrindo a linguagem Perl
Descobrindo a linguagem Perl
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix it
 
Synapseindia object oriented programming in php
Synapseindia object oriented programming in phpSynapseindia object oriented programming in php
Synapseindia object oriented programming in php
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate Frameworks
 
Shortcodes In-Depth
Shortcodes In-DepthShortcodes In-Depth
Shortcodes In-Depth
 
Object Oriented PHP5
Object Oriented PHP5Object Oriented PHP5
Object Oriented PHP5
 
WordPress London 16 May 2012 - You don’t know query
WordPress London 16 May 2012 - You don’t know queryWordPress London 16 May 2012 - You don’t know query
WordPress London 16 May 2012 - You don’t know query
 
Bioinformatics p5-bioperl v2013-wim_vancriekinge
Bioinformatics p5-bioperl v2013-wim_vancriekingeBioinformatics p5-bioperl v2013-wim_vancriekinge
Bioinformatics p5-bioperl v2013-wim_vancriekinge
 
Your code sucks, let's fix it! - php|tek13
Your code sucks, let's fix it! - php|tek13Your code sucks, let's fix it! - php|tek13
Your code sucks, let's fix it! - php|tek13
 
Bioinformatica p6-bioperl
Bioinformatica p6-bioperlBioinformatica p6-bioperl
Bioinformatica p6-bioperl
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix it
 
Coffeescript: No really, it's just Javascript
Coffeescript: No really, it's just JavascriptCoffeescript: No really, it's just Javascript
Coffeescript: No really, it's just Javascript
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of Lithium
 
Smelling your code
Smelling your codeSmelling your code
Smelling your code
 

Similar to Introduction to Moose

What's New in Perl? v5.10 - v5.16
What's New in Perl?  v5.10 - v5.16What's New in Perl?  v5.10 - v5.16
What's New in Perl? v5.10 - v5.16Ricardo Signes
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConRafael Dohms
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Kang-min Liu
 
Perl from the ground up: objects and testing
Perl from the ground up: objects and testingPerl from the ground up: objects and testing
Perl from the ground up: objects and testingShmuel Fomberg
 
Advanced modulinos
Advanced modulinosAdvanced modulinos
Advanced modulinosbrian d foy
 
Building a Pluggable Plugin
Building a Pluggable PluginBuilding a Pluggable Plugin
Building a Pluggable PluginBrandon Dove
 
Improving Dev Assistant
Improving Dev AssistantImproving Dev Assistant
Improving Dev AssistantDave Cross
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency InjectionRifat Nabi
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Jeff Carouth
 
Perl Bag of Tricks - Baltimore Perl mongers
Perl Bag of Tricks  -  Baltimore Perl mongersPerl Bag of Tricks  -  Baltimore Perl mongers
Perl Bag of Tricks - Baltimore Perl mongersbrian d foy
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix itRafael Dohms
 
究極のコントローラを目指す
究極のコントローラを目指す究極のコントローラを目指す
究極のコントローラを目指すYasuo Harada
 

Similar to Introduction to Moose (20)

mro-every.pdf
mro-every.pdfmro-every.pdf
mro-every.pdf
 
wget.pl
wget.plwget.pl
wget.pl
 
What's New in Perl? v5.10 - v5.16
What's New in Perl?  v5.10 - v5.16What's New in Perl?  v5.10 - v5.16
What's New in Perl? v5.10 - v5.16
 
OOP in PHP.pptx
OOP in PHP.pptxOOP in PHP.pptx
OOP in PHP.pptx
 
Bag of tricks
Bag of tricksBag of tricks
Bag of tricks
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)
 
Perl from the ground up: objects and testing
Perl from the ground up: objects and testingPerl from the ground up: objects and testing
Perl from the ground up: objects and testing
 
Presentation1
Presentation1Presentation1
Presentation1
 
DBI
DBIDBI
DBI
 
Advanced modulinos
Advanced modulinosAdvanced modulinos
Advanced modulinos
 
Perl object ?
Perl object ?Perl object ?
Perl object ?
 
Oops in php
Oops in phpOops in php
Oops in php
 
Building a Pluggable Plugin
Building a Pluggable PluginBuilding a Pluggable Plugin
Building a Pluggable Plugin
 
Improving Dev Assistant
Improving Dev AssistantImproving Dev Assistant
Improving Dev Assistant
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
 
Perl Bag of Tricks - Baltimore Perl mongers
Perl Bag of Tricks  -  Baltimore Perl mongersPerl Bag of Tricks  -  Baltimore Perl mongers
Perl Bag of Tricks - Baltimore Perl mongers
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix it
 
究極のコントローラを目指す
究極のコントローラを目指す究極のコントローラを目指す
究極のコントローラを目指す
 

Recently uploaded

Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Neo4j
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 

Recently uploaded (20)

Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptxVulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 

Introduction to Moose

  • 2. What we expect from OOP ● Classes (methods, types, attributes, open recursion...) ● Encapsulation ● Aggregation ● Message passing and dynamic dispatch ● Inheritance and polymorphism ● Abstraction Skip definitions
  • 3. Classes ● Templates for defining objects state and behavior
  • 4. Encapsulation ● Specifying which classes may use the members of an object e.g: public, protected or private, determining whether they are available to all classes, sub-classes or only the defining class.
  • 5. Aggregation ● Object containing another object
  • 6. Message passing and dynamic dispatch ● Message passing is the process by which an object sends data to another object or asks the other object to invoke a method ● when a method is invoked on an object, the object itself determines what code gets executed by looking up the method at run time in a table associated with the object (needed when multiple classes contain different implementations of the same method )
  • 7. Inheritance and polymorphism ● allows the programmer to treat derived class members just like their parent class's members ("Subclasses" are more specialized versions of a class, which inherit attributes and behaviors from their parent classes, and can introduce their own.) ● a class has all the state and behavior of another class - polymorphism
  • 8. What OOP features offers Perl? ● MOP in Perl5: ● Class - package ● Object - blessed reference (a scalar type holding a reference to object data – object may be a hash, array, or reference to subroutine.) ● Method - a subroutine within a package ● Constructor – a method that returns reference to blessed variable
  • 9. What OOP features offers Perl? package Car; sub new { my $class = shift; my $brand = shift; my $self = {}; $self->{'brand'} = $brand; bless ($self, $class); return $self; }
  • 10. What OOP features offers Perl? ● Encapsulation – in general only by convention. ● Some tricks: private variable, private method, private function package Mom; package Kido; sub new{ use base qw(Mom); my $class = shift; my $self = { sub ask_for_pin{ 'CARD_PIN' => '0000', my $self = shift; }; my $how = shift; return &{$self}($how); my $closure = sub { } my $arg = shift; if ($arg and $arg eq 'nice'){ return $self->{'CARD_PIN'}; package main; } my $mom = Mom->new(); else { my $kido = Kido->new(); return 'forget!'; } print $kido->ask_for_pin('not nice'); }; print $kido->ask_for_pin('nice'); bless($closure, $class); return $closure; }; ● “Inside-out” classes not handy... “There is only one way to do it...” .
  • 11. 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 readyn"; } } } sub make_cookies{ _prepare_pastry(); package main; print "cookies readyn"; (...) } package main; } my $mom = Mom->new(); package main; $mom->make_cookies(); (...) my $mom = Mom->new(); $mom->_prepare_pastry(); #this compiles! $mom->make_cookies();
  • 12. What OOP features offers Perl? ● Aggregation package Person; my $eva = Person->new(); my $car1 = Car->new(); sub new { $car1->brand( 'Fiat' ); my $class = shift; my $self = {}; $eva->cars->[0]->brand(); #returns 'Fiat' $self->{'cars'} = (); bless( $self, $class ); return $self; } sub cars { my $self = shift; my $car = shift; if ( ref( $car ) eq 'Car' ) { push @{ $self->{'cars'} }, $car; } return $self->cars; }
  • 13. What OOP features offers Perl? ● Inheritance (multi-object) and polymorphism: use base() package Person; package Employee; sub new { use base qw(Person); my $class = shift; my $self = {}; sub new { my $class = shift; bless( $self, $class ); my $job = shift; return $self; my $self = $class->SUPER::new(); } $self->{'job'} = $job; sub name { bless( $self, $class ); my $self = shift; return $self; if ( @_ ) { $self->{'name'} = shift } } return $self->{'name'}; } #overriding sub say_name { sub say_name { my $self = shift; my $self = shift; $self->SUPER::say_name(); printf( "My name is %s. n", $self->{'name'} ); printf( "My job is %s.n", $self->{'job'} ); } } #inheritance and polymorphism my $adam = Employee->new( 'Developer' ); $adam->name( 'Adam' ); $adam->say_name
  • 14. What OOP features offers Perl? ● Abstraction – only objects package File; my $bmp = BMP->new(); use Carp; $bmp->load(); sub new { my $jpg = JPG->new(); my $class = shift; $jpg->load(); my $self = {}; bless ($self, $class); return $self; } 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"; }
  • 15. 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... There is more than one way to do it!
  • 16. Moose There is more than one way to do it, but sometimes consistency is not a bad thing either!
  • 17. Moose is Perl. Moose = Class::MOP + semantic
  • 18. Moose is Perl. ● common system for building classes ● new levels of code reuse, allowing you to improve your code with features that would otherwise be too complex or expensive to implement
  • 19. Moose is Perl. Everything missing in OO Perl you can find in Moose + some important bonuses! ● 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 … and much more.
  • 20. Moose – first example. Sets strict and warnings package Vehicle; use Moose; MOOSE CLASS has 'RegNum' => ( Class attributes. 'is' => 'rw', 'isa' => 'Str'); sub goto{ my $self = shift; Class methods. my $place_name = shift; print "Going to $place_name n"; } __PACKAGE__->meta->make_immutable; no Moose; 1; use Vehicle; We get new() for free my $avehicle = Vehicle->new(); $acar->RegNum('123456'); print $acar->RegNum; We get also default $acar->goto('Oriente'); accessors for free.
  • 21. 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 = @_; my $self = { '_RegNum' => undef }; if ( exists( $args{'RegNum'} ) && defined( $args{'RegNum'} ) ) { $self->{'_RegNum'} = $args{'RegNum'}; } return bless($self, $class); } package Vehicle; use Moose; sub RegNum { my $self = shift; has 'RegNum' => ( my $regnum = shift; 'is' => 'rw', if ( $regnum ) { 'isa' => 'Str'); $self->{'_RegNum'} = $regnum; } sub goto{ return $self->{'_RegNum'}; my $self = shift; } my $place_name = shift; print "Going to $place_name n"; sub goto{ } my $self = shift; my $place_name = shift; no Moose; print "Going to $place_name n"; 1; } 1;
  • 22. Lets have a closer look... ● Arguments (...) 'rw' or 'ro' – tells which accessors will be created has 'RegNum' => ( 'is' => 'rw', 'isa' => 'Str' ); Moose types: (...) Bool, Str, Num, Int, ArrayRef, HashRef, and more 'is' – defines if argument is read-write or read-only 'isa' – defines type of the attribute (and validate it during assignment)
  • 23. Lets have a closer look... ● Read- only arguments has 'RegNum' => ( If we restrict access to the attribute... 'is' => 'ro', the default accessor won't be created. 'isa' => 'Str' ); This method doesn't exist $avehicle->RegNum('123456'); – it results in compilation error The only right moment to set up the my $avehicle = Vehicle->new( attribute is during initialization. 'RegNum'=>'1234' ); We can still read it wherever we want. print $avehicle->RegNum."n";
  • 24. 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(); my $avehicle = Vehicle->new('RegNum'=>'123456'); ...but we still can have illegal vehicle.. RegNum can be set to empty string. my $avehicle = Vehicle->new('RegNum'=>''); has 'RegNum' => ( 'is' => 'ro', 'required' => 1, ); BUT my $avehicle = Vehicle->new('RegNum'=>undef); If attribute has no type it can be set to undefined
  • 25. What more we can do with attributes? ●Clearer and predicate Imagine... the vehicle is a broken and is waiting to be scraped, but first you must unregister it . has 'RegNum' => ( 'is' => 'ro', You can't use accessors because it is “ro”. 'isa' => 'Str', 'required'=> 1, 'clearer' => 'unregister', but... you can set clearer to clean the value 'predicate'=>'is_registered', ); and predicate to check if the value exists my $avehicle = Vehicule->new('RegNum'=>'1234'); print $avehicle->RegNum; $avehicle->unregister(); if (!$avehicle->is_registered()){ The method you get for free. print "Vehicle illegal!.n"; }
  • 26. What more we can do with attributes? ● Subtypes Not every string can be the registration number... package Vehicle; use TypeConstraints use Moose; and create subtype use Moose::Util::TypeConstraints; subtype 'RegistrationNo' => as 'Str', parent type => where { /^(dd)(-)(ww)(-)(dd)$/ }, => message {"$_ is not valid registration number."}; has 'RegNum' => ( compare $_ to something 'is' => 'ro', 'isa' => 'RegistrationNo', 'required'=> 1, 'clearer' => 'unregister', and use it 'predicate'=>'is_registered', ); my $avehicle = Vehicle->new('RegNum'=>'11-xx-22'); Subtypes can be more complex more examples here #my $avehicle = Vehicle->new('RegNum'=>'111-xx-22');
  • 27. One Step Further - MooseX. ● Custom types Lets define where is our vehicle.... a 2D coordinate - two points: x and y that must have positive value. 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.'}; A coordinate that is a has of two valid points subtype Coordinate, as HashRef, where { Point->check( $_->{'X'} ) and Point->check( $_->{'Y'} )}, message {'Incorect coordinate.'.$_ }; This is very useful type. We can pack it in separate package and reuse later.
  • 28. One Step Further - MooseX. ●Custom types Lets use the coordinate to define where is the vehicle. use MyTypes qw( Coordinate ); import custom type (...) has 'place' => ( modify the vehicle class 'is' => 'rw', 'isa' => Coordinate, (Vehicle.pm) ); (...) my $place = {'X'=>1, 'Y'=>3 }; $avehicle->place( $place ); use it where ever you need
  • 29. One Step Further - MooseX. ● Custom types and coercion In the end, in class definition, But maybe it would be easier to use it this way...? Don't forget to turn on the coercion on the argument $avehicle->place( [4,5] ); 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;
  • 30. Private attributes – only convention. The vehicle may change its place only when it moves ? (...) This is what the manual says #an attribute to be publicly readable, but only privately settable. – but this is only CONVENTION. has '_place' => ( 'is' => 'ro', 'isa' => Coordinate, 'coerce' => 1, 'writer' => '_set_place', ); reader and writer redefine the names of custom accessors sub goto{ my $self = shift; my $coordinate = shift; $self->_set_place($coordinate); } Now we can “move” the vehicle. (...) $avehicle->goto([7,8]); print Dumper($avehicle); print 'The vehicle is at'.$avehicle->_place->{'X'}.','.$avehicle->_place- >{'Y'}.'.'; #my $place = {'X'=>1, 'Y'=>3 }; However this still would work. #my $other_place = [4,5]; MOOSE is PERL #$avehicle->_set_place( $place );
  • 31. Method modifiers Mileage – every time the vehicle moves its mileage increase. has '_mileage' => ( One more 'is' => 'ro', 'isa' => 'Num', private attribute. 'required' => 1, 'default' => 0, 'writer' => '_set_mileage', ); Method modifier Has access to attributes, around 'goto' => sub { before they are modified by my $orig = shift; my $self = shift; method my $coordinate1 = $self->_place; my $x1 = $coordinate1->{'X'}; my $y1 = $coordinate1->{'Y'}; Executing main method #@_ stores new coordinate $self->$orig(@_); my $coordinate2 = $self->_place; my $x2 = $coordinate2->{'X'}; Accessing modified my $y2 = $coordinate2->{'Y'}; attributes my $distance = sqrt(($x1-$x2)**2+($y1-$y2)**2); $self->_set_mileage($self->_mileage + $distance); other actions };
  • 32. Method modifiers Mileage – every time the vehicle moves its mileage increase. Define default value has '_place' => ( 'is' => 'ro', 'isa' => Coordinate, 'coerce' => 1, 'writer' => '_set_place', 'default' => sub {[0,0]}, ); 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
  • 33. Lazy, lazy_build and trigger. Imagine we want to sell the vehicle. The price depends on the mileage. Lazy - value is calculated only when has 'price' => ( 'is' => 'ro', it is accessed and is unset. 'isa' => 'Num', 'predicate'=>'has_price', 'lazy_build'=>1, 'builder'=>'calculate_price', lazy + clearer = lazy_build 'init_arg'=>undef, ); sub calculate_price { Lazy needs default value or builder my $self = shift; my $price = 100000; if ($self->_mileage != 0){ $price = $price / $self->_mileage; } return $price; Method building the value. } $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;
  • 34. Lazy, lazy_build and trigger. Let's run the clearer automatically. has '_mileage' => ( Every time the mileage changes the 'is' => 'ro', clearer for price attribute is triggered. 'isa' => 'Num', 'required' => 1, 'default' => 0, 'writer' => '_set_mileage', 'trigger' => sub { my $self=shift; After this change the previous example $self->clear_price; shows updated value every time we access it } ); Lazy build is very useful for attributes are expensive to calculate – we calculate it only while reading. sub sell_vehicle { my $self = shift; $self->clear_price; return $self->price; We can also use method instead the trigger. } The price is updated every time we read it $avehicle->goto([1,1]); using the method. print $avehicle->price; Useful for expensive calculation. $avehicle->goto([4,5]); print $avehicle->price; print "The final price: ".$avehicle->sell_vehicle. "n";
  • 35. Code reuse - inheritance in Moose. Is the vehicle car or bike? package Car; use Moose; Parent class extends 'Vehicle'; has 'fuel' =>( 'is' => 'rw', 'isa' => 'Int', 'default'=>0, New attribute ); sub refuel { my $self = shift; $self->fuel($self->fuel + 10); New method } override goto => sub{ my $self = shift; Overwritten method if($self->fuel eq 0){ print 'No fuel'; return; } return super; }; Calling super no Moose
  • 36. Code reuse - inheritance in Moose. package Bike; use Moose; extends 'Vehicle'; has '+RegNum' => ( 'required'=> 0, ); changing inherited attribute no Moose; 1; my $abike = Bike->new(); registration number is not linger required
  • 37. Better code reuse – inheritance and roles. Short explanation: ● Role is a “state or behavior that can be shared between classes.” ● 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.
  • 38. Better code reuse – inheritance and roles. We can create a 'truck' role and use it in our vehicle. The only difference package Truck; sub do_load { use Moose::Role; my $self = shift; my $load = shift; has 'capacity' => ( 'is' => 'ro', if(($self->capacity >= $load) and !$self->load){ 'isa' => 'Int', $self->load(1); 'default'=>10, }else{ 'required'=>1, print 'Load unsuccessful,'; ); } } has 'load' => ( sub do_unload { 'is' => 'rw', my $self = shift; 'isa' => 'Bool', my $load = shift; 'default'=>0, ); if($self->load){ $self->load(0); }else{ print 'Nothing to unload,'; } } We create a piece of functionality no Moose; 1; exactly the same way as we were creating a moose class.
  • 39. Better code reuse – inheritance and roles. We want to have a car with a “truck functionality” - a lorry. package Lorry; use Moose; extends 'Car'; with 'Truck'; Lorry = Car with Truck role no Moose; 1; How to use Lorry? Lorry is a vehicle – mast have registration number. (…) use Lorry; (…) Lorry has a Truck role – mast have capacity. my $alorry = Lorry->new('RegNum'=>'11-xx-23', 'capacity'=>50); #$alorry->do_load(100); - more than 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); #$alorry->goto([2,4]); - still can't go without the fuel But Lorry is still a car so won't go without fuel.
  • 40. Better code reuse – inheritance and roles. In the end we want to assure that the truck role will be only used with anything that uses fuel (Have you ever seen a lorry-bike?) 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'; no Moose; Since bike doesn't use fuel this code will not compile. 'Truck' requires the method 'fuel' to be implemented by 'Lorrybike' at /usr/local/lib/perl5/site_perl/5.10.0/i386-linux-thread-multi/Moose/Meta/Role/Application.pm line 51 Moose::Meta::Role::Application::apply('Moose::Meta::Role::Application::ToClass=HASH(0xa5faa2c)', 'Moose::Meta::Role=HASH(0xa5f6a6c)', 'Moose::Meta::Class=HASH(0xa5f8754)') called at /usr/local/lib/perl5/site_perl/5.10.0/i386-linux-thread-multi/Moose/Meta/Role/Application/ToClass.pm line 31 (...)
  • 41. BUILDARGS and BUILD Let's go back to Vehicle. It would be awesome to create a vehicle this way : $acar = Vehicule->new('11-xx-11'); BUILDARGS method is called as a class method around BUILDARGS => sub { before an object is created. It has direct access my $orig = shift; to arguments passed in method call. my $class = shift; my %a = @_; my %args = (); if ( @_ == 1 ) { $args{ 'RegNum' } = $_[0]; return $class->$orig( %args ); } return $class->$orig( %a ); };
  • 42. BUILDARGS and BUILD There is a possibility to have a bike without registration. But we want to be warn about it... BUILD method is called after an object is created. sub BUILD { my $self = shift; if(!$self->RegNum){ if($self->isa('Bike')){ print "Vehicle without registration number.n"; } } } We will be warn about creating a bike without a registration number. my $abike = Bike->new(); my $abike2 = Bike->new('22-yy-66');
  • 43. Aggregation and Native Traits Let's create a garage for our vehicles. package Garage; Notice: there is no use Moose; use Moose::Util::TypeConstraints; 'is' =>'ro|rw' has 'vehicles' => ( 'isa'=> 'ArrayRef[ Vehicle ]', 'default' => sub {[]}, 'traits' => ['Array'], 'handles'=> { Trait – a role added to attribute. 'add_vehicle' => 'push', Here we make the vehicles attribute 'get_vehicle' => 'shift', work as an array. }, ); 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...
  • 44. 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(); $acar2 and $acar is the same (reference to the same object)
  • 45. What more you can do in Moose? For example: ● Delegation - "proxy" methods call some other method on an attribute. ● Custom traits - MooseX ● Custom OO system – sub-classing methaclasses ● And much more...
  • 46. Some tips ● If you don't know what is wrong try to load package from command line : perl -Ilib/ -e 'use Coordinate' ● $object->dump for debugging
  • 47. More information: ● 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/ ● Moose::Manual and Moose::Cookbook