Subject: | Composing a role with a class which has been instantiated should be an error |
In Moose, attempting to compose a role with an immutable class results in an error.
In Moo, it doesn't (see attached scripts moose-immutable.pl and moo-immutable.pl). The documentation for Moo indicates that it does something similar to Moose's
__PACKAGE__->meta->make_immutable;
upon first instantiation of an object, but discusses only make_immutable's role in creating an inlined constructor. Moo's constructor is indeed immutable, but one can add arbitrary attributes to the class after an instantiation.
I belive that Moo should follow Moose's behavior here. Moo's classes are semi-immutable, which can lead to unexpected behavior.
I think it would also be of value to recognize an explicit request to make the class immutable, i.e., turn
__PACKAGE__->meta->make_immutable
into an op, rather than a no-op. At times I'd like to explicitly make a class immutable as a defensive measure; bringing that part of Moose's toolbox to Moo would be a real benefit (provided that the disparity in behavior which is the subject of this report is resolved).
Thanks,
Diab
Subject: | moo-immutable.pl |
use 5.10.0;
use strictures 1;
package C1 {
use Moo;
has a1 => ( is => 'ro', default => 'a1' );
__PACKAGE__->meta->make_immutable;
}
package R1 {
use Moo::Role;
has r1 => ( is => 'ro', default => 'r1' );
}
my $o1 = C1->new;
say $o1->a1;
use Moo::Role();
Moo::Role->apply_role_to_package( 'C1', 'R1' );
my $o2 = C1->new;
say $o1->r1 // 'undefined but existant attribute r1';
say $o2->r1 // 'undefined but existant attribute r1';
Subject: | moose-immutable.pl |
use 5.10.0;
use strictures 1;
use Moose::Util qw/ apply_all_roles /;
package C1 {
use Moose;
has a1 => ( is => 'ro', default => 'a1' );
no Moose;
__PACKAGE__->meta->make_immutable;
}
package R1 {
use Moose::Role;
has r1 => ( is => 'ro', default => 'r1' );
}
my $o1 = C1->new;
apply_all_roles( 'C1', 'R1' );
my $o2 = C1->new;
say $o1->r1 // 'undefined but existent attribute r1';
say $o2->r1 // 'undefined but existent attribute r1';