Moose::Spec::Role(3)

πŸ‘‘ Moose::Spec::Role β€” the formal spec for Role behavior πŸ’…

okay bestie, buckle up. This is Moose::Spec::Role(3) from the User Contributed Perl Documentation, and it's the ✨formal spec✨ for how Roles behave. Grab a strawberry πŸ“, we're going in.


✨ VERSION ✨

version 2.4000 β€” yes she's on 2.4000, iconic.


🌸 DESCRIPTION 🌸

NOTE: This document is currently incomplete.

(not me reading a spec that openly admits it's a WIP 😭 love the honesty tho)

πŸŽ€ Components of a Role

πŸ’œ Excluded Roles

A role can carry a list of excluded roles β€” basically roles it should never be composed with. And it's not just the direct composition you have to worry about, no no. It's also the "inherited" composition. The way that exclusion travels up the chain? yeah, that's the whole point.

This feature was lifted from the Fortress language, and it's genuinely most useful when you're building a big ol' pile of role "building blocks" where a couple of them should absolutely never, ever be used together. 🚫

πŸ’œ Attributes

A role's attributes are like a class's attributes, except β€” plot twist β€” they don't actually get applied. So any method that an attribute accessor would normally generate? Not generated in the role. Nope. Those only get created once the role is actually applied to a class. Delayed gratification, main character energy. ✨

πŸ’œ Methods

These are the methods defined inside the role. Simple as that. No cap. πŸ’…

πŸ’œ Required Methods

A role can require a consuming class (or role) to hand over a given method. If a class fails to do that, it's a fatal error. If it's a role that fails, it just passes the method requirement along to its consuming role. Chain of custody, bestie. πŸ”—

πŸ’œ Required Attributes

Just like a role can require methods, it can also require attributes. And here's the rule: the attribute that fulfills the requirement must implement at least as much as is required. So for example β€” if the role says the attribute has to be read-only, then the fulfilling attribute must at least have a reader (it can also have a writer, that's fine). And if the role says the attribute has to be an ArrayRef, then it must be either an ArrayRef or a subtype of an ArrayRef. Meet the bar or go home. 🫢

πŸ’œ Overridden Methods

The override and super keywords are allowed in roles, but their behavior is different from their class counterparts. In a class, super points directly at that class's superclass. In a role, super is deferred β€” it has no meaning until the role gets composed into a class. Once that composition happens, super then refers to that class's superclass. πŸ¦‹

And this is key, so write it on your mirror: roles do not have hierarchy, so they can never have a super role. Periodt. πŸ’€

πŸ’œ Method Modifiers

These are the before, around and after modifiers you know and love from Moose classes. The difference here? The modifiers are not actually applied until the role is composed into a class. (This is exactly like attributes and the override keyword β€” same energy.) 🌈

🧚 Role Composition

🌟 Composing into a Class

Topics on deck:

  • Excluded Roles
  • Required Methods
  • Required Attributes
  • Attributes
  • Methods
  • Overridden methods
  • Method Modifiers (before, around, after)

🌟 Composing into a Instance

(no extra deets here, that's just the heading, moving on πŸ’–)

🌟 Composing into a Role

  • Excluded Roles
  • Required Methods
  • Required Attributes
  • Attributes
  • Methods
  • Overridden methods
  • Method Modifiers (before, around, after)

🌟 Role Summation

When multiple roles get added to another role (using the with @roles keyword), the roles are composed symmetrically. The product of that composition is a composite role β€” that's Moose::Meta::Role::Composite, bestie. ✨

πŸ“ Excluded Roles

(no extra deets, just vibes)

πŸ“ Required Methods

(no extra deets, just vibes)

πŸ“ Required Attributes

(no extra deets, just vibes)

πŸ“ Attributes

Attributes with the same name will conflict, and that's considered an unrecoverable error. Like, we don't even look at any other aspect of the attribute β€” if the names clash, that's already enough. Done. πŸ’€

And why so harsh and so early? Because there's so much room for variance between two attributes that the problem explodes immediately and the rules get insanely complex. The author's opinion, stated right there in the spec: that complexity is not worth the trouble.

πŸ“ Methods

Methods with the same name will conflict too β€” but no error gets thrown! Instead, the method name just gets added to the list of required methods for the new composite role. Chill conflict, honestly. 😌

Set theory time, because we're that girl: each role can be said to have a set of methods. The symmetric difference of the two sets becomes the new set of methods for the composite role, and the intersection of the two sets is the conflicts. Illustrated like so:

Role A has method set { a, b, c }
Role B has method set { c, d, e }

The composite role (A,B) has
    method   set { a, b, d, e }
    conflict set { c }

πŸ“ Overridden methods

An overridden method can conflict in one of two ways.

  1. First way: it clashes with another overridden method of the same name. That's an unrecoverable error β€” and it's an obvious one, because you literally cannot override a method twice in the same class. πŸ™ˆ
  2. Second way: an overridden method and a regular method share a name. Also an unrecoverable error, because there's no way to combine the two, and it's not okay for both of them to end up composed into a single class at some point.

Using override in roles can be tricky β€” but if you use it carefully, it can be a very powerful tool. πŸ‘‘

πŸ“ Method Modifiers (before, around, after)

Method modifiers are the only place where the ordering of role composition matters. That's just the nature of method modifiers themselves. πŸ¦‹

Since a method can have multiple method modifiers, they're simply collected in order, so they can later be applied to the class in that same order.

In general, great care should be taken when using method modifiers in roles. That order sensitivity can totally lead to subtle, hard-to-find bugs if you overuse them. As with all good things in life, moderation is the key. πŸ”₯

πŸ’… Composition Edge Cases

This is just a little collection of complex edge cases that are easy to get confused about. It tries to clarify those cases and explain what's actually going on in them.

⭐ Role Method Overriding

So many people want to "override" methods in the roles they're consuming. That works great for classes β€” the local class method gets favored over the role method. But in roles it's trickier, because conflicts mean neither method is chosen and the method gets "required" instead. 😭

Here's an example of that (incorrect) type of overriding:

package Role::Foo;
use Moose::Role;

sub foo { ... }

package Role::FooBar;
use Moose::Role;

with 'Role::Foo';

sub foo { ... }
sub bar { ... }

Here the foo methods conflict, and Role::FooBar now requires any class or role consuming it to implement foo. Which is very often not what the user wanted. πŸ™ˆ

Now here's an example of the (correct) type of overriding β€” except it's not overriding at all, as the text below explains:

package Role::Foo;
use Moose::Role;

sub foo { ... }

package Role::Bar;
use Moose::Role;

sub foo { ... }
sub bar { ... }

package Role::FooBar;
use Moose::Role;

with 'Role::Foo', 'Role::Bar';

sub foo { ... }

This works because the combination of Role::Foo and Role::Bar produces a conflict on the foo method. That conflict means the composite role (created by combining Role::Foo and Role::Bar using the with keyword) has a method requirement of foo. And then Role::FooBar fulfills that requirement. ✨

It's important to note: Role::FooBar is simply fulfilling the required foo method, and NOT overriding foo. That distinction is important, bestie. Write it down. πŸŽ€

And now another example of a (correct) type of overriding, this time using the excludes option:

package Role::Foo;
use Moose::Role;

sub foo { ... }

package Role::FooBar;
use Moose::Role;

with 'Role::Foo' => { -excludes => 'foo' };

sub foo { ... }
sub bar { ... }

By specifically excluding the foo method during composition, we let Role::FooBar define its own version of foo. Slay. πŸ’…


πŸ¦‹ SEE ALSO πŸ¦‹

Traits

Roles are based on Traits, which originated over in the Smalltalk community.

  • <http://www.iam.unibe.ch/~scg/Research/Traits/> β€” This is the main site for the original Traits papers. πŸ“š
  • Class::Trait β€” I created this implementation of traits several years ago, after reading the papers linked above. (This module is now maintained by Ovid and I am no longer involved with it.)

Roles

Since roles are relatively new, and the Moose implementation is probably the most mature one out there, there isn't much to link to. But here are some bits worth looking at (mostly Perl 6 related):


πŸ‘‘ 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.


and that's the whole thing bestie 🫢 this was perl v5.42.0, dated 2025-07-25, served to you fresh as Moose::Spec::Role(3) β€” go forth and compose your roles responsibly πŸ’œβœ¨

πŸ“¦ where this page comes from