Переберите экземпляр базового класса Perl Moose в подкласс - PullRequest
1 голос
/ 26 июня 2019

(я думаю) Я хочу иметь возможность преобразовать экземпляр базового класса в подкласс.Я не пытался решать это как роль, но подклассы чувствуют себя лучше для моей ситуации.Я получаю ошибку компиляции при попытке переопределить метод.Похоже, это связано с моим использованием моего подкласса в базовом классе.

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 override / super sugar.Я чувствую, что мой код не проходит тест на запах, поэтому я подожду лучшего ответа, прежде чем опубликовать это изменение в качестве ответа.

sub make_forecast {
    my $self = shift;

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

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

}

РЕДАКТИРОВАТЬ: Похоже, мне нужно описать мой проект больше.У меня есть танки, которые представлены с общими атрибутами, такими как местоположение, название, вместимость, текущий уровень и т. Д. Мне нужно создавать прогнозы на определенный день.Я чувствую, что хочу всего этого в одном классе, но я не хочу загрязнять стандартный класс танков вещами прогнозирования.Добавление роли, статически или динамически, было не совсем правильным.Я думал, что преобразование объекта резервуара в резервуар с прогнозируемым объектом будет работать, что и создало ошибку, описанную в этом посте.Я также поиграл с тем, чтобы сделать класс прогноза отдельным от танка и использовать делегирование ему из экземпляра танка, но это кажется немного более грубым.Вздох.Надеюсь, это поможет.Я все еще пытаюсь определить лучший дизайн для этого и действительно ценю любые идеи.

...