In Moose, if a role defines an attribute with a default, how do I change that default in my consuming class?

StackOverflow https://stackoverflow.com/questions/15325518

  •  22-03-2022
  •  | 
  •  

Pergunta

My Moose class consumes a role which I'm not allowed to change. That role defines an attribute with a default. I need my class to have that attribute, but with a different default.

Is that possible?

All I could come up with is surrounding the "new" method with some of my own code, as follows:

around new => sub {
    my ($orig, $self) = (shift, shift);
    return $self->$orig(@_, the_attribute => $new_value);
}

But I'm not sure if surrounding new is valid, and was also hoping for something more elegant.

Foi útil?

Solução

A better, simpler way is to write this in your class:

has '+the_attribute' => (
    default => sub{1},
}

has with a + lets you override just a specific property of an attribute.

Much simpler than surrounding BUILDARGS.

Outras dicas

You have the right idea, but you shouldn't override new. Moose::Manual::BestPractices says:

Never override new

Overriding new is a very bad practice. Instead, you should use a BUILD or BUILDARGS methods to do the same thing. When you override new, Moose can no longer inline a constructor when your class is immutabilized.

It's been a while since I've done this, but I think the following will do the trick:

around BUILDARGS => sub {
   my $orig  = shift;
   my $class = shift;
   return $self->$orig(
      the_attribute => $new_value,
      @_ == 1 ? %{ $_[0] } : @_,
   );
};

Notes:

  • I placed the new attribute first to allow it to be overridden.
  • I made it so both ->new({ ... }) and ->new(...) still work. You could use @_ instead of @_ == 1 ? %{ $_[0] } : @_ if you don't care about breaking ->new({ ... }).
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top