Метод доступа к атрибутам, не удовлетворяющий требованию роли при использовании Moops и Moose

Рассмотрим следующий пример кода:

use Moops;

role RoleA
using Moose {
  requires 'm1';
  method m2() {
    $self->m1." World!\n";
  }
}

role RoleB
using Moose {
  has 'm1' => ( accessor => 'm1', is => 'ro', isa => 'Str', default => 'Hello');
}

class ClassA
with RoleB
with RoleA
using Moose {
  method m3() {
    $self->m2();
  }
}

print ClassA->new()->m3();

"Компиляция" завершается неудачно, так как средство доступа к атрибуту не удовлетворяет запросу ролей для m1:

$ perl roletest.pl 
'RoleB|RoleA' requires the method 'm1' to be implemented by 'ClassA' at /usr/lib/perl5/site_perl/Moose/Meta/Role/Application/ToClass.pm line 134.
    Moose::Meta::Role::Application::ToClass::check_required_methods('Moose::Meta::Role::Application::ToClass=HASH(0x28b9d00)', 'Moose::Meta::Role::Composite=HASH(0x28c6270)', 'Moose::Meta::Class=HASH(0x28ee7c0)') called at /usr/lib/perl5/site_perl/Moose/Meta/Role/Application.pm line 55
    Moose::Meta::Role::Application::apply('Moose::Meta::Role::Application::ToClass=HASH(0x28b9d00)', 'Moose::Meta::Role::Composite=HASH(0x28c6270)', 'Moose::Meta::Class=HASH(0x28ee7c0)') called at /usr/lib/perl5/site_perl/Moose/Meta/Role/Application/ToClass.pm line 36
    Moose::Meta::Role::Application::ToClass::apply('Moose::Meta::Role::Application::ToClass=HASH(0x28b9d00)', 'Moose::Meta::Role::Composite=HASH(0x28c6270)', 'Moose::Meta::Class=HASH(0x28ee7c0)', 'HASH(0x28e3410)') called at /usr/lib/perl5/site_perl/Moose/Meta/Role.pm line 470
    Moose::Meta::Role::apply('Moose::Meta::Role::Composite=HASH(0x28c6270)', 'Moose::Meta::Class=HASH(0x28ee7c0)') called at /usr/lib/perl5/site_perl/Moose/Util.pm line 163
    Moose::Util::_apply_all_roles('Moose::Meta::Class=HASH(0x28ee7c0)', undef, 'RoleB', 'RoleA') called at /usr/lib/perl5/site_perl/Moose/Util.pm line 99
    Moose::Util::apply_all_roles('Moose::Meta::Class=HASH(0x28ee7c0)', 'RoleB', 'RoleA') called at /usr/lib/perl5/site_perl/Moose.pm line 66
    Moose::with('Moose::Meta::Class=HASH(0x28ee7c0)', 'RoleB', 'RoleA') called at /usr/lib/perl5/site_perl/Moose/Exporter.pm line 409
    Moose::with('RoleB', 'RoleA') called at roletest.pl line 16
    main::BEGIN() called at roletest.pl line 23
    eval {...} called at roletest.pl line 23
BEGIN failed--compilation aborted at roletest.pl line 23.

Используя равнину Moose а также Moose::Role это работает (как задокументировано здесь). Кроме того, не используя Moose Бэкэнд работает на.

Я уже пытался переключить порядок with Заявления безрезультатны. Замена атрибута объявлением метода решает проблему, но мне нужен способ указать требования к атрибуту.

Есть ли способ заставить это работать?

1 ответ

Решение

Вы уверены, что это работает с простым Moose? Потому что я пробовал это, и это не удается с очень похожим сообщением об ошибке:

use v5.14;
use strict;
use warnings;

package RoleA {
    use Moose::Role;
    requires 'm1';
    sub m2 {
        my $self = shift;
        $self->m1." World!\n";
    }
}

package RoleB {
    use Moose::Role;
    has 'm1' => ( accessor => 'm1', is => 'ro', isa => 'Str', default => 'Hello');
}

package ClassA {
    use Moose;
    with qw/ RoleB RoleA /;
    sub m3 {
        my $self = shift;
        $self->m2();
    }
}

print ClassA->new()->m3();

В Moose существует ряд проблем (и соответствующих тестовых примеров TODO в наборе тестов), связанных с атрибутами в ролях, которые не удовлетворяют requires в других ролях. Например, ошибка RT#77406 похожа (но не идентична).

ОБНОВЛЕНИЕ, вручную составляя роли по одному, в определенном порядке, вы можете заставить его работать:

use Moops;

role RoleA using Moose {
  requires 'm1';
  method m2() {
    $self->m1." World!\n";
  }
}

role RoleB using Moose {
  has 'm1' => ( is => 'ro', isa => 'Str', default => 'Hello' );
}

class ClassA using Moose {
  with 'RoleB';
  with 'RoleA';
  method m3() {
    $self->m2();
  }
}

print ClassA->new()->m3();
Другие вопросы по тегам