将Perl Moose基类实例重定义为子类

时间:2019-06-26 18:38:40

标签: perl inheritance moose

(我认为)我希望能够将基类实例转换为子类。我没有尝试将其作为角色来解决,但是子类化对我的情况更好。尝试覆盖方法时收到编译错误。这似乎与我在基类中使用子类有关。

Tank.pm

package Tank;

use Moose;
use Tank::Forecast;

has id => (
    isa      => 'Int',
    is       => 'ro',
    required => 1,
);

sub make_forecast {
    my $self = shift;
    my $date = shift;

    return Tank::Forecast->meta->rebless_instance( $self, date => $date );
}

1;

Tank / Forecast.pm

    package Tank::Forecast;

    use Moose;

    extends 'Tank';

    has date => (
        isa      => 'Str',
        is       => 'ro',
        required => 1,
    );

    has end_volume => (
        isa     => 'Num',
        is      => 'ro',
        default => sub { rand() },
    );

    override 'make_forecast' => sub {
        my $self = shift;

        Tank->meta->rebless_instance_back($self);

        return super();
    };
  1;

test.pl

use Tank;

my $tank = Tank->new( id => 1 );
$tank->make_forecast('2019-06-27');
print $tank->end_volume . "\n";
$tank->make_forecast('2019-06-28');
print $tank->end_volume . "\n";

这会产生编译错误:

You cannot override 'make_forecast' because it has no super method at /home/carl/perl5/perlbrew/perls/perl-5.16.3/lib/site_perl/5.16.3/i686-linux/Moose/Exporter.pm line 419
    Moose::override('make_forecast', 'CODE(0x1871e70)') called at Tank/Forecast.pm line 25
    require Tank/Forecast.pm at Tank.pm line 4
    Tank::BEGIN at Tank/Forecast.pm line 0
    eval {...} at Tank/Forecast.pm line 0
    require Tank.pm at test.pl line 1
    main::BEGIN at Tank/Forecast.pm line 0
    eval {...} at Tank/Forecast.pm line 0
Compilation failed in require at Tank.pm line 4.
BEGIN failed--compilation aborted at Tank.pm line 4.
Compilation failed in require at test.pl line 1.
BEGIN failed--compilation aborted at test.pl line 1.

我愿意就设计和使其实际工作的最佳方法提出建议。

编辑:删除Moose替代/超级糖后,我的代码似乎可以正常工作。我确实感觉我的代码没有通过气味测试,所以我将等待更好的答案,然后再将此更改发布为答案。

sub make_forecast {
    my $self = shift;

    # This removes existing Forecast attributes
    Tank->meta->rebless_instance_back($self);

    return $self->SUPER::make_forecast(@_);

}

编辑:看来我需要更多地描述我的项目。我的战车用诸如位置,名称,容量,当前水位等一般属性表示。我需要为特定日期创建预测。我觉得我希望所有这些都放在一个类中,但是我不想用预测的东西来污染标准的坦克类。静态或动态添加角色均不正确。我认为将一个坦克对象转换为带有预测对象的坦克是可行的,这就是造成本文所述错误的原因。我也喜欢使预测类与坦克分离,并从坦克实例使用委派给它,但这似乎有点笨拙。叹。我希望这有帮助。我仍在尝试为此找到最佳设计,并非常感谢任何想法。

0 个答案:

没有答案