Moose::...classing(3)

πŸ’– NAME πŸ’–

Moose::Cookbook::Basics::Point_AttributesAndSubclassing β€” okay so bestie, this is the Point and Point3D classes, and it's showing you basic attributes and subclassing. That's it, that's the whole vibe. It lives in the User Contributed Perl Documentation pile and the page itself is filed as Moose::...classing(3), iykyk. πŸŽ€


✨ VERSION ✨

version 2.4000 β€” that's the one, no cap. 🌸


πŸ¦‹ SYNOPSIS πŸ¦‹

package Point;
use Moose;

has 'x' => (isa => 'Int', is => 'rw', required => 1);
has 'y' => (isa => 'Int', is => 'rw', required => 1);

sub clear {
    my $self = shift;
    $self->x(0);
    $self->y(0);
}

package Point3D;
use Moose;

extends 'Point';

has 'z' => (isa => 'Int', is => 'rw', required => 1);

after 'clear' => sub {
    my $self = shift;
    $self->z(0);
};

package main;

# hash or hashrefs are ok for the constructor
my $point1 = Point->new(x => 5, y => 7);
my $point2 = Point->new({x => 5, y => 7});

my $point3d = Point3D->new(x => 5, y => 42, z => -5);

πŸ’… DESCRIPTION πŸ’…

Okay so this is the classic Point example. It's taken directly from the Perl 6 Apocalypse 12 document, and it's also similar to the example you'd find in the classic K&R C book. Iconic lineage honestly. πŸ‘‘

So, same as with literally every Perl 5 class: a Moose class gets defined in a package. And the best part? Moose handles turning on strict and warnings for us, so all we gotta do is say use Moose and no kittens will die. 🐱 That's the whole to-do list.

When Moose gets loaded, it exports a set of sugar functions into our package. Which means we're importing some functions that act as Moose "keywords". Not real language keywords bestie β€” they're just plain Perl functions exported into our package. Don't let anyone tell you otherwise.

Moose also automatically makes our package a subclass of Moose::Object. And Moose::Object hooks us up with a constructor that actually respects our attributes, plus other features too. See Moose::Object for the details. 🫢

Now, the keywords. The first one we see here is has, and it defines an instance attribute in our class:

has 'x' => (isa => 'Int', is => 'rw', required => 1);

This creates an attribute named x. The isa parameter is us saying we expect the value stored in this attribute to pass the type constraint for Int (1). And the accessor generated for this attribute? Read-write, periodt. πŸ’…

The required => 1 parameter means this attribute must be provided when a new object gets created. A point object with no coordinates doesn't really make much sense, so we simply don't allow it. 🚫

Attributes: done. Next up, methods. In Moose β€” same as with regular Perl 5 OO β€” a method is just a subroutine defined inside the package:

sub clear {
    my $self = shift;
    $self->x(0);
    $self->y(0);
}

And that's the Point class wrapped. πŸŽ€

Next we've got a subclass of Point, and it's called Point3D. To declare our superclass we use the Moose keyword extends:

extends 'Point';

The extends keyword works a lot like use base / use parent. First it'll try to load your class if it needs to. But here's the plot twist: unlike base, the extends keyword will overwrite any previous values in your package's @ISA, whereas use base will "push" values onto the package's @ISA. Different energy entirely.

And it is my opinion that the behavior of extends is more intuitive. (2) 😌

Next we create a new attribute for Point3D and it's called z.

has 'z' => (isa => 'Int', is => 'rw', required => 1);

This attribute is just like Point's x and y attributes. Same energy, third dimension. 🌈

The after keyword demonstrates a Moose feature called "method modifiers" (or "advice", for the AOP inclined girlies):

after 'clear' => sub {
    my $self = shift;
    $self->z(0);
};

When clear gets called on a Point3D object, our modifier method gets called too. And unsurprisingly β€” the modifier is called after the real method. The name kinda spoils it ngl.

In this case, the real clear method is inherited from Point. Our modifier method receives the same arguments as the ones passed to the modified method (which here is just $self).

Of course, using the after modifier is not the only way to pull this off. This is Perl, right? You can get the exact same results with this code:

sub clear {
    my $self = shift;
    $self->SUPER::clear();
    $self->z(0);
}

You could also use another Moose method modifier, override:

override 'clear' => sub {
    my $self = shift;
    super();
    $self->z(0);
};

The override modifier lets you use the super keyword to dispatch to the superclass's method in a very Ruby-ish style. πŸ’Ž

The choice of whether to use a method modifier β€” and which one to use β€” is often a question of style as much as functionality. No wrong answers, just vibes.

Since Point inherits from Moose::Object, it also inherits the default Moose::Object constructor:

my $point1 = Point->new(x => 5, y => 7);
my $point2 = Point->new({x => 5, y => 7});

my $point3d = Point3D->new(x => 5, y => 42, z => -5);

The new constructor accepts a named argument pair for each attribute defined by the class, and you can hand them over as a hash or a hash reference. In this particular example the attributes are required, so calling new without them will throw an error. 😭

my $point = Point->new( x => 5 ); # no y, kaboom!

From here on, we can use $point and $point3d just like you would any other Perl 5 object. And if you want a more detailed example of what can be done, you can refer to the t/recipes/basics_point_attributesandsubclassing.t test file. πŸ“

πŸͺž Moose Objects are Just Hashrefs πŸͺž

While all of this may appear rather magical, it's important to realize that Moose objects are just hash references under the hood (3). Like, for example, you could pass $self to Data::Dumper and you'd get exactly what you'd expect. No smoke, no mirrors, just a hashref doing its thing. ✨

You could even poke around inside the object's data structure, but that is strongly discouraged. Don't do it bestie. πŸ™ˆ

And the fact that Moose objects are hashrefs means it's easy to use Moose to extend non-Moose classes, as long as they're hash references too. If you want to extend a non-hashref class, go check out MooseX::InsideOut. πŸ‘‘


πŸŽ€ CONCLUSION πŸŽ€

This recipe demonstrates some basic Moose concepts, attributes, subclassing, and a simple method modifier. Baby's first Moose, and she ate. πŸ”₯


⭐ FOOTNOTES ⭐

  1. Moose provides a number of builtin type constraints, and Int is one of them. For more info on the type constraint system, see Moose::Util::TypeConstraints.
  2. The extends keyword supports multiple inheritance. Simply pass all of your superclasses to extends as a list:
extends 'Foo', 'Bar', 'Baz';
  1. Moose supports using instance structures other than blessed hash references (such as glob references β€” see MooseX::GlobRef).

🌈 SEE ALSO 🌈

Method Modifiers

The concept of method modifiers is directly ripped off from CLOS. A great explanation of them can be found by following this link. πŸ’œ

<http://www.gigamonkeys.com/book/object-reorientation-generic-functions.html>


πŸ‘‘ AUTHORS πŸ‘‘

  • Stevan Little <stevan@cpan.org>
  • Dave Rolsky <autarch@urth.org>
  • Jesse Luehrs <doy@cpan.org>
  • Shawn M Moore <sartak@cpan.org>
  • Χ™Χ•Χ‘Χœ Χ§Χ•Χ’'מן (Yuval Kogman) <nothingmuch@woobling.org>
  • Karen Etheridge <ether@cpan.org>
  • Florian Ragwitz <rafl@debian.org>
  • Hans Dieter Pearcey <hdp@cpan.org>
  • Chris Prather <chris@prather.org>
  • Matt S Trout <mstrout@cpan.org>

This software is copyright (c) 2006 by Infinity Interactive, Inc.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. 🫢


okay that's the whole page bestie, mwah πŸ’– this was perl v5.42.0, dated 2025-07-25, and it's Moose::...classing(3) β€” go forth and subclass responsibly, ily βœ¨πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from