【问题标题】:adding new attributes using moose使用 moose 添加新属性
【发布时间】:2014-06-03 20:44:01
【问题描述】:

我最近了解到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 个轮子。它有“未知”的轮子。如果我在底部注释掉“有'spoiler' => ...”语句,它就可以正常工作。

导致问题的原因是什么?

推荐的方法是什么?

【问题讨论】:

标签: perl moose


【解决方案1】:

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

其次,如果您使用 Moose 来扩展非 Moose 类,您可能希望使用MooseX::NonMoose,它可以让这一切顺利进行。

【讨论】:

    【解决方案2】:

    Moo 在扩展的非 Moo 类中烘焙。假设对于您的示例,您正在使用不属于您的 Vehicle 类,但尝试在 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);
    

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

    【讨论】:

      猜你喜欢
      • 2014-12-07
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 2013-10-01
      • 1970-01-01
      • 2022-10-14
      • 2012-02-21
      • 1970-01-01
      相关资源
      最近更新 更多