OK, here's my take on how the Batmobile could be modelled with roles. It would be cute if it weren't also scary crazy.

use v5.14; package Role::Switchable { use Moose::Role; has _switchable_base_class => ( is => 'ro', writer => '_set_switchable_base_class', clearer => '_clear_switchable_base_class', default => sub { ref($_[0])->Moose::Util::find_meta }, isa => 'Class::MOP::Class', ); has switchable_role => ( init_arg => undef, is => 'ro', writer => '_set_switchable_role', predicate => 'has_switchable_role', clearer => '_clear_switchable_role', isa => 'Moose::Meta::Role', ); has _switchable_data => ( init_arg => 'switchable', is => 'ro', writer => '_set_switchable_data', clearer => '_clear_switchable_data', default => sub { +{} }, isa => 'HashRef[HashRef]', ); sub BUILD { } after BUILD => sub { my ($self, $params) = @_; $self->_switchable_data->{_} = $params; if (my $role = delete $params->{switchable_role}) { $self->switch_role($role); } }; around dump => sub { my $next = shift; my $self = shift; my $tmp_class = $self->_switchable_base_class; $self->_clear_s +witchable_base_class; my $tmp_role = $self->switchable_role; $self->_clear_s +witchable_role; my $tmp_data = $self->_switchable_data; $self->_clear_s +witchable_data; my $r = $self->$next(@_); $self->_set_switchable_base_class($tmp_class); $self->_set_switchable_role($tmp_role); $self->_set_switchable_data($tmp_data); return $r; }; sub switch_role { my $self = shift; my ($new_role, %new_attrs) = @_; $new_role = $new_role->Moose::Util::find_meta if defined($new_role) && !ref($new_role); my $meta = $self->Moose::Util::find_meta; if ( $self->has_switchable_role ) { my $current_role = $self->switchable_role; # Keep current attribute values my %attr_values; for ($current_role->get_attribute_list) { my $attr = $meta->find_attribute_by_name($_); $attr_values{ $attr->name } = $attr->get_value($self) if $attr->has_value($self); } $self->_switchable_data->{ $current_role->name } = \%attr_ +values; # Rebless back to base class before applying new. $self->_switchable_base_class->rebless_instance_back($self +); $self->_clear_switchable_role; } if ($new_role) { my %attrs = ( %{ $self->_switchable_data->{ $new_role->name } or {} +}, %new_attrs, ); my $class = Moose::Util::with_traits($self->_switchable_ba +se_class->name, $new_role->name); $self->_set_switchable_role($new_role); $class->Moose::Util::find_meta->rebless_instance($self, %a +ttrs); } return; } } package Car { use Moose::Role; has wheels => (is => 'rw'); sub drive { say 'driving' } } package Plane { use Moose::Role; has wings => (is => 'ro'); sub fly { say 'flying' } } package Boat { use Moose::Role; sub float { say 'floating' } } package Batmobile { use Moose; has owner => (is => 'rw'); with 'Role::Switchable'; } my $bat = Batmobile->new( owner => 'Bruce Wayne', switchable => { Plane => { wings => 'blue' }, Car => { wheels => 'red' }, }, ); $bat->switch_role('Car'); say $bat->wheels, " wheels"; $bat->drive if $bat->can('drive'); $bat->fly if $bat->can('fly'); print $bat->dump; $bat->switch_role('Boat'); $bat->owner('Batman'); print $bat->dump; $bat->switch_role('Plane'); say $bat->wings, " wings"; $bat->drive if $bat->can('drive'); $bat->fly if $bat->can('fly'); print $bat->dump;
use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name

In reply to Re^7: Remove roles for an object in perl moose by tobyink
in thread Remove roles for an object in perl moose by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.