我最近了解了Moose
。当我在子类中创建一个新属性时,它似乎以某种方式覆盖应该工作的其他函数......
use strict; use warnings;
################################### VEHICLE ####################################
package Vehicle;
sub new{
my $classname = shift;
bless { wheels=>'unknown', color=>'unknown', @_ } => $classname
}
sub wheels{
my $vehicle = shift;
return $$vehicle{wheels}
}
sub setWheels{
my $vehicle = shift;
$$vehicle{wheels} = $_[0];
}
##################################### CAR ######################################
package Car;
use Moo; extends 'Vehicle';
sub new{
my $classname = shift;
my $vehicle = vehicle->new( @_ );
$vehicle->setWheels(4);
bless $vehicle => $classname
}
has 'spoiler' => ( is=>'rw', reader=>'rspoil', writer=>'setSpoiler' );
1
问题在于,当我创建一个Car对象时,它没有4个轮子。它有未知的'车轮。如果我发表评论"有扰流板' => ..."在底部的声明,它工作得很好。
导致问题的原因是什么?
我在做什么的推荐方法是什么?
答案 0 :(得分:3)
首先,如果你使用Moose编写一个类,你应该永远不要定义自己的方法new
。请参阅Moose best practices。
其次,如果您使用Moose扩展非Moose类,您可能希望使用能够使所有工作都顺利进行的MooseX::NonMoose。
答案 1 :(得分:3)
Moo在扩展的非Moo类中进行了烘焙。假设你的例子中你正在使用一个不属于你的汽车类,但试图在Moo中编写子类,这里是如何做的。
在Moo *中,你没有申报新的。它为您处理。您可以通过声明BUILD子例程来改变状态 - 这将在实例化从父对象到子对象的实例化对象之后运行。因此:
use strict; use warnings;
################################### VEHICLE ####################################
package Vehicle;
sub new{
my $classname = shift;
bless { wheels=>'unknown', color=>'unknown', @_ } => $classname
}
sub wheels{
my $vehicle = shift;
return $$vehicle{wheels}
}
sub setWheels{
my $vehicle = shift;
$$vehicle{wheels} = $_[0];
}
##################################### CAR ######################################
package Car;
use Moo; extends 'Vehicle';
sub BUILD {
my $self = shift;
if ($self->wheels eq 'unknown') {
$self->setWheels(4);
}
}
has 'spoiler' => ( is=>'rw', reader=>'rspoil', writer=>'setSpoiler' );
package Main;
use strict;
use warnings;
use Data::Printer;
p(Car->new(spoiler => 'big', color => 'bright red'));
my $strangecar = Car->new(spoiler => 'piddly', color => 'yellow', wheels => 3);
p($strangecar);
$strangecar->setWheels(6);
$strangecar->setSpoiler('not so piddly');
p($strangecar);
<强>输出强>
Car {
Parents Vehicle
public methods (4) : BUILD, new, rspoil, setSpoiler
private methods (0)
internals: {
color "bright red",
spoiler "big",
wheels 4
}
}
Car {
Parents Vehicle
public methods (4) : BUILD, new, rspoil, setSpoiler
private methods (0)
internals: {
color "yellow",
spoiler "piddly",
wheels 3
}
}
Car {
Parents Vehicle
public methods (4) : BUILD, new, rspoil, setSpoiler
private methods (0)
internals: {
color "yellow",
spoiler "not so piddly",
wheels 6
}
}
要为父母和孩子使用Moo,您可以这样做:
use strict; use warnings;
################################### VEHICLE ####################################
package Vehicle;
use Moo;
has 'wheels' => ( is=>'rw', writer=>'setWheels', default => sub { 'unknown' });
has 'color' => (is => 'rw', default => sub { 'unknown' });
##################################### CAR ######################################
package Car;
use Moo; extends 'Vehicle';
has 'spoiler' => ( is=>'rw', reader=>'rspoil', writer=>'setSpoiler' );
has '+wheels' => ( default => sub {4} );
package Main;
use strict;
use warnings;
use Data::Printer;
p(Car->new(spoiler => 'big', color => 'bright red'));
my $strangecar = Car->new(spoiler => 'piddly', color => 'yellow', wheels => 3);
p($strangecar);
$strangecar->setWheels(6);
$strangecar->setSpoiler('not so piddly');
p($strangecar);
产生与上述代码类似的输出。