Perl 使用moose添加新属性

Perl 使用moose添加新属性,perl,moose,Perl,Moose,我最近了解到。当我在子类中创建一个新属性时,它似乎以某种方式覆盖了其他应该工作的函数 use strict; use warnings; ################################### VEHICLE #################################### package Vehicle; sub new{ my $classname = shift; bless { wheels=>'unknown', color=>'

我最近了解到。当我在子类中创建一个新属性时,它似乎以某种方式覆盖了其他应该工作的函数

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
问题是,当我创建汽车对象时,它没有4个轮子。它有“未知”的轮子。如果我注释掉底部的“has'spoiler'=>…”语句,它就可以正常工作了

是什么导致了这个问题


推荐的方法是什么?

首先,如果您使用Moose编写类,您应该不要定义自己的名为
new
的方法。看


其次,如果您使用Moose来扩展一个非Moose类,您可能希望使用能够使所有工作非常顺利的方法。

首先,如果您使用Moose编写一个类,您应该永远不要定义自己的名为
new
的方法。看


其次,如果您使用Moose来扩展一个非Moose类,那么您可能希望使用能够使所有工作都非常顺利的Moose类。

Moo在扩展的非Moo类中烘焙。假设在您的示例中,您使用的是一个不属于您的Vehicle类,但试图用Moo编写子类,下面介绍如何操作

在Moo*中,您不需要声明新的。它会帮你处理的。您可以通过声明一个构建子例程来改变状态-这将在从父对象到子对象实例化实例化对象后运行。因此:

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);

这将产生与上述代码类似的输出。

Moo在扩展的非Moo类中烘焙。假设在您的示例中,您使用的是一个不属于您的Vehicle类,但试图用Moo编写子类,下面介绍如何操作

在Moo*中,您不需要声明新的。它会帮你处理的。您可以通过声明一个构建子例程来改变状态-这将在从父对象到子对象实例化实例化对象后运行。因此:

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);
这将产生与上述代码类似的输出。

您根本没有使用,这可能是您应该做的。您根本没有使用,这可能是您应该做的。