Close
Close

Using Moose in Perl


You have learned about Perl's core object-oriented programming. Moose is an object system provided by CPAN to make object-oriented programming easier. We can also build great things without Moose but it requires much less coding with Moose.

Moose can be installed from CPAN. For Linux, we can use the following command in terminal:

cpan
cpan[1]> install Moose

Let's create our first class using Moose.

package Square;

use Moose;

1;

And that's it. Moose automatically sets up use strict and use warnings for us. So, we don't have to write them explicitly. Also, Moose adds a default constructor called new. It means that we have to write only this much code and then we are ready to make objects of our class using my $obj = Square->new;. Let's do this.

use strict;
use warnings;

use Square;

my $obj1 = Square->new;
my $obj2 = Square->new;
Output

Attributes


We can easily give an attribute like side to our Square class using Moose's has function. Let's see this working.

package Square;

use Moose;

has 'side' =>(is => 'ro', isa => 'Int');

1;
use strict;
use warnings;
use feature ':5.10';

use Square;

my $obj1 = Square->new(side => 5);
my $obj2 = Square->new(side => 10);

say $obj1->side;
say $obj2->side;
Output
5
10

has 'side' =>(is => 'ro', isa => 'Int'); has 'side' tells us that the Square objects have a side attribute and is => 'ro' means that this attribute is read only and we cannot change the value of side after assigned once.

isa => 'Int' means that the Square's attribute 'side' can have only integer values. Giving other values will give us an error. We can also omit isa => 'Int' to pass any value of 'side' and not only integers.

If we want to change the value of side after assigning once and don't want it be only read only, then we can use is => 'ro'. This will make 'side' readable and writable.

Let's see an example:

package Square;

use Moose;

has 'side' =>(is => 'rw');

1;
use strict;
use warnings;
use feature ':5.10';

use Square;

my $obj1 = Square->new(side => 5);

say $obj1->side;

$obj1->side("string");

say $obj1->side;
Output
5
string

You can see that we have changed the value of 'side' because it is 'rw'.

We have omitted isa=>'Int' and that's why we are able to assign it string values also.

Notice that we have written $obj1->side("string"); to change the value of the 'side' and not $obj1->side = "string".

Let's see one more example:

package Student;

use Moose;

has 'name' =>(is => 'ro', isa => 'Str', default=>"xyz");
has 'roll' =>(is => 'ro', isa => 'Int', default=>0);

1;
use strict;
use warnings;
use feature ':5.10';

use Student;

my $obj1 = Student->new(name => 'Sam',roll=>1);
my $obj2 = Student->new;

say $obj1->name;
say $obj1->roll;

say $obj2->name;
say $obj2->roll;
Output
Sam
1
xyz
0

The only new thing in this example is default. Using default=>"xyz" with the attribute 'name' will assign 'xyz' to 'name' if nothing is passed while making objects of the Student class. Similary, default=>0 with the attribute 'roll' will assign 0 to 'roll' if nothing is passed while making objects of the Student class.

We can also have writer to change the value of an attribute. The following example shows how to do this.

package Student;

use Moose;

has 'name' =>(is => 'ro', isa => 'Str', default=>"xyz");
has 'roll' =>(is => 'ro', isa => 'Int', default=>0);
has 'passed' =>(is => 'ro', isa =>'Bool', default=>0, writer=>'_set_passed');

sub pass{
  my $self = shift;
  $self->_set_passed(1);
}

1;

We have used isa=>'Bool' to give only boolean value to the attribute 'passed'. We were able to change the value of passed because the writer option of passed created a private accessor which was usable within the class to set its value.

Inheritance


You are already familiar with inheritance. So, let's start doing this with Moose.

We use extends 'PARENT_CLASS' in the child class to extend PARENT_CLASS. Let's see an example on this:

package Student;

use Moose;

has 'name' =>(is => 'ro', isa => 'Str', default=>"xyz");
has 'roll' =>(is => 'ro', isa => 'Int', default=>0);
has 'passed' =>(is => 'ro', isa =>'Bool', default=>0, writer=>'_set_passed');

sub pass{
  my $self = shift;
  $self->_set_passed(1);
}

1;
package Btech;

use Moose;

extends 'Student';

1;
use strict;
use warnings;
use feature ':5.10';

use Btech;

my $obj1 = Btech->new(name => 'Sam',roll=>1);

say $obj1->name;
say $obj1->roll;
Output
Sam
1

So, you can see that we used extends 'Student' in Btech to inherit Student.

We can also modify attributes of a parent class in child class using + before the name of the attribute. Let's see an example to understand this.

package Student;

use Moose;

has 'name' =>(is => 'ro', isa => 'Str', default=>"xyz");
has 'roll' =>(is => 'ro', isa => 'Int', default=>0);
has 'passed' =>(is => 'ro', isa =>'Bool', default=>0, writer=>'_set_passed');

sub pass{
  my $self = shift;
  $self->_set_passed(1);
}

1;
package Btech;

use Moose;

extends 'Student';

has '+name' =>(default=>'Unknown B.Tech student');

1;
use strict;
use warnings;
use feature ':5.10';

use Btech;

my $obj1 = Btech->new;

say $obj1->name;
say $obj1->roll;
Output
Unknown B.Tech student
0

You can see that we have changed the default value of Btech's name using has '+name' in the Btech class.

Method Overriding


You are also familiar with method overriding. Now, let's start doing this with Moose.

We use override to override a method.

#file is Student.pm

package Student;

use Moose;

has 'name' =>(is => 'ro', isa => 'Str', default=>"xyz");
has 'roll' =>(is => 'ro', isa => 'Int', default=>0);
has 'passed' =>(is => 'ro', isa =>'Bool', default=>0, writer=>'_set_passed');

sub pass{
  my $self = shift;
  $self->_set_passed(1);
}

sub speak{
  print "I am student\n";
}

1;
#file is Btech.pm
package Btech;

use Moose;

extends 'Student';

has '+name' =>(default=>'Unknown B.Tech student');

override 'speak' => sub{
  print "I am B.Tech student\n";
  super();
};

1;
#Btech.pl
use strict;
use warnings;
use feature ':5.10';

use Btech;

my $obj1 = Btech->new;
my $obj2 = Student->new;

$obj1->speak;
$obj2->speak;
Output
I am B.Tech student
I am student

The super() function calls the nearest parent's implementation of the current method.


Ask Yours
Post Yours
Doubt? Ask question