Classes created using Mic are provided with a generated constructor.
This default constructor supports two forms of usage described below.
For objects constructed using keyword parameters, the constructor should be passed a hashref containing the keyword parameters.
Imagine a counter that starts from a user supplied value, so we can use it this way
use Test::More tests => 3; use Example::Construction::Counter; my $counter = Example::Construction::Counter->new({start => 10}); is $counter->next => 10; is $counter->next => 11; is $counter->next => 12;
The class and implementation:
package Example::Construction::Counter; use Mic::Class interface => { object => { next => {}, }, class => { new => {} } }, implementation => 'Example::Construction::Acme::Counter'; 1; package Example::Construction::Acme::Counter; use Mic::Impl has => { COUNT => { init_arg => 'start' }, }, ; sub next { my ($self) = @_; $self->[COUNT]++; } 1;
Here the 'count' attribute is bound to the 'start' constructor parameter using the init_arg declaration.
For objects constructed using positional parameters, the constructor should be passed a list of positional parameters. These parameters will be passed to the BUILD special method (described in the next section) as an array ref.
As an example, consider a set object that we'd create by passing a list of items.
use Test::More tests => 3; use Example::Construction::Set_v1; my $set = Example::Construction::Set_v1->new(1 .. 4); ok $set->has(1); ok ! $set->has(5); $set->add(5); ok $set->has(5);
This can be acheieved using the BUILD special method.
package Example::Construction::Set_v2; use Mic::Class interface => { object => { add => {}, has => {}, size => {}, }, class => { new => {} } }, implementation => 'Example::Construction::Acme::Set_v2', ; 1;
In the implementation, we convert the argument array to a hash
package Example::Construction::Acme::Set_v2; use Mic::Impl has => { SET => { default => sub { {} }, } }, ; sub BUILD { my ($self, $args) = @_; $self->[SET] = { map { $_ => 1 } @{ $args } }; } sub has { my ($self, $e) = @_; exists $self->[SET]{$e}; } sub add { my ($self, $e) = @_; ++$self->[SET]{$e}; } sub size { my ($self) = @_; scalar(keys %{ $self->[SET] }); } 1;
If this subroutine is defined, it will be called by the default constructor and will receive the newly created object and either a hashref of named parameters or an arrayref of positional parameters depending on whether the constructor was passed a hashref or list respectiively.
This is useful for carrying out any post-construction logic e.g. object validation.
It can also be used to process constructor arguments, e.g. the counter implementation above can also be written using BUILD instead of init_arg (though init_arg is preferable due to being more concise).
package Example::Construction::Acme::Counter_v2; use Mic::Impl has => { COUNT => { }, }, ; sub BUILD { my ($self, $arg) = @_; $self->[COUNT] = $arg->{start}; } sub next { my ($self) = @_; $self->[COUNT]++; } 1;
If the default constructor is not flexible enough and you need to write your own constructor, this can be done with the aid of builders.
Each class has a corresponding Builder. Within a class method, the Builder is obtained by calling the builder_for routine (see example below).
builder_for
A builder has the following construction related methods
This creates a new instance, in which attributes with declared defaults are populated with those defaults, and all others are populated with undef. A hashref can also be supplied, in which case it is used to populate the attributes.
This can be used in a class method to invoke the BUILD method for an object after the object is created.
We'll rewrite the counter example above providing a new method:
new
package Example::Construction::Acme::CounterWithNew; use Mic::Impl has => { COUNT => { }, }, classmethod => ['new'], ; sub next { my ($self) = @_; $self->[COUNT]++; } sub new { my ($class, $start) = @_; my $builder = Mic::builder_for($class); my $obj = $builder->new_object({COUNT => $start}); return $obj; }; 1;
Note that new must be tagged as a 'classmethod' for this to work.
To install Mic, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Mic
CPAN shell
perl -MCPAN -e shell install Mic
For more information on module installation, please visit the detailed CPAN module installation guide.