Your SlideShare is downloading. ×
Introduction to Moose
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Introduction to Moose

3,286

Published on

Moose is a framework for Perl 5 build on top of Class::MOP, that brings all features of object-oriented programming.

Moose is a framework for Perl 5 build on top of Class::MOP, that brings all features of object-oriented programming.

Published in: Technology
1 Comment
5 Likes
Statistics
Notes
No Downloads
Views
Total Views
3,286
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
63
Comments
1
Likes
5
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. MooseOOP for Perl.
  • 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 classs 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. MooseThere 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 yourcode with features that would otherwise be too complex orexpensive to implement
  • 19. Moose is Perl.Everything missing in OO Perl you can find in Moose + someimportant 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 moreis – defines if argument is read-write or read-onlyisa – 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 wont be created. isa => Str ); This method doesnt 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, ); BUTmy $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 predicateImagine... the vehicle is a broken and is waiting to be scraped, but first you must unregister it .has RegNum => ( is => ro, You cant 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 existsmy $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? ● SubtypesNot 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 typesLets define where is our vehicle.... a 2D coordinate - two points: x and y thatmust have positive value.package MyTypes; what we want to createuse Moose;use MooseX::Types -declare => [qw(Coordinate Point)];use MooseX::Types::Moose qw(Int HashRef); what we use to createsubtype Point, as Int, a point where { $_>= 0}, message {Must be positive number.}; A coordinate that is a has of two valid pointssubtype 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 typesLets 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...? Dont 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 accessorssub 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 modifiersMileage – 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 modifiersMileage – 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 didnt 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.Lets 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 classextends 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 superno Moose
  • 36. Code reuse - inheritance in Moose.package Bike;use Moose;extends Vehicle;has +RegNum => ( required=> 0, ); changing inherited attributeno 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 – cant be subclassed, cant be extended … we cant 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 cant go without the fuel But Lorry is still a car so wont 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 doesnt 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 BUILDLets 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 BUILDThere 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 TraitsLets 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 TraitsLets 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 dont 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 Revolutionhttp://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

×