Moose is an extension for Perl 5 that allows you to simplify the implementation of OOP.
Creating a class is very easy:
package MyClass; use Moose;
all empty class created. It can have an arbitrary number: attributes, methods, superclasses, method modifiers, a constructor (1 item), a destructor (1 item) and a meta-class (1 item) that contains all the meta-information about this class.
')
Now more about these components:
Class
Each class is a subclass of Moose :: Object. By default, it creates a bunch of useful objects, in the form of meta-classes and other objects inherent in the superclass, which can be accessed after creation.
Subclass
Inheritance happens with the keyword
extends package User; use Moose; extends 'Person'; has 'username' => ( is => 'rw' );
multiple inheritance, specify classes separated by commas: extends 'Foo', 'Bar';
Attributes
There must be a name for the attribute, it may have a different number of properties: read / write flag, type, accessor method, delegations, default value, etc.
By default, Moose stores attributes in a class instance as a hash. Access to them can be obtained through accessors.
has - declare attribute
has 'first_name' => ( is => 'rw' );
the is option can have the values [ro | rw | bare] read-only either read-write or bare - without accessors to this attribute.
Getters and setters can be installed as follows:
has 'weight' => ( is => 'rw', reader => 'get_weight', writer => 'set_weight', );
predicate - if the attribute is “undef” or another false value, it will return true.
clearer - reset attribute
clearer - reset attribute
has 'ssn' => ( is => 'rw', clearer => 'clear_ssn', predicate => 'has_ssn', );
$person->has_ssn;
The need to set the attribute
can be set using the property: required => 1
By default, all attributes are optional.
Attributes can be set by default in two ways.
has 'size' => ( is => 'ro', default => 'medium', predicate => 'has_size', );
and if not installed in the constructor, then:
my $person = Person->new(); $person->size;
And you can set a link to the method:
has 'size' => ( is => 'ro', default => sub { ( 'small', 'medium', 'large' )[ int( rand 3 ) ] }, predicate => 'has_size', );
Alternative method:
has 'size' => ( is => 'ro', builder => '_build_size', predicate => 'has_size', ); sub _build_size { return ( 'small', 'medium', 'large' )[ int( rand 3 ) ]; }
builder recommend using instead of
default .
We postpone the installation of the attribute last
This can be achieved by setting the property: lazy => 1
Especially necessary when the initial value of the attribute depends on other factors.
Another advantage of using this property is that the attribute will be calculated only if it is required, and if it is not needed at all, then we will save CPU time.
Types of attributes
can be the same type as any pearl structure: isa => 'Str'
or they can be an object: does => 'MyApp :: Object'
Setting multiple attributes
has [ 'x', 'y' ] => ( is => 'ro', isa => 'Int' );
or so:
for my $name ( qw( xy ) ) { my $builder = '_build_' . $name; has $name => ( is => 'ro', isa => 'Int', builder => $builder ); }
Methods
Any function declared in a class is a class method.
Method Modifiers
called before (or "before, after, around, augment") method call:
before 'atribute' => sub { my $self = shift; my $a = shift; print $a; };
Role
The behavior or state that this class should implement. Analogue interface in other languages.
Created using use Moose :: Role;
package Eq; use Moose::Role; requires 'equal_to'; sub not_equal_to { my ( $self, $other ) = @_; not $self->equal_to($other); }
although the role looks like a class, but it is not a class, you cannot create an instance of the role. The word
requires tells us that any class using this role must implement the 'equal_to' method.
package Comparable; use Moose; with 'Eq'; sub equal_to { my ( $self, $other ) = @_; $self->compare($other) == 0; } sub compare { my ( $self, $other ) = @_; $self->amount <=> $other->amount; }
Designer / Destructor
They never need to be explicitly redefined, but if such a need arises, you can use BUILD () and DEMOLISH () for the constructor and destructor, respectively.
Metaclass
The metaclass describes the class. With Moose, each class gives a "meta ()", which returns a Moose :: Meta :: Class object. He talks about what this class is.
my $meta = User->meta(); for my $attribute ( $meta->get_all_attributes ) { print $attribute->name(), "\n"; if ( $attribute->has_type_constraint ) { print " type: ", $attribute->type_constraint->name, "\n"; } } for my $method ( $meta->get_all_methods ) { print $method->name, "\n"; }
Trash cleaning
happens if set at the beginning of the class: use namespace :: autoclean;
or at the end of the class: no Moose;
Acceleration of classes
If the class in the process of work does not change, then its work can be accelerated as follows:
__PACKAGE__->meta->make_immutable;
That's all, this knowledge should be enough to successfully create OOP structures in Perl, but for a deeper understanding, of course, it is better to delve into the documentation and ... yes and yes into the source code of the modules (well, this is for special cases, although in this case, curiosity will not hurt anyone).