Почему ролевое приложение Moose с модификаторами методов не работает в моем коде? - PullRequest
3 голосов
/ 15 февраля 2010

У меня есть роль и несколько классов, которые смешивают роль. Класс Role загружает все реализующие классы, так что все, что импортирует Blah, может использовать их, не набирая много строк 'use'.

package Blah;
use Moose::Role;

use Blah::A;
use Blah::B;
(etc...)

requires '...';
requires 'foo';
around 'foo' => sub { ... }

Типичный подкласс Бла:

package Blah::A;
use Moose;
with 'Blah';

sub foo { ... }

__PACKAGE__->meta->make_immutable;

Поскольку каждый метод подкласса 'foo' начинается с одних и тех же битов кода, роль также реализует их через модификатор метода.

Проблема в том, что Moose не применяет модификатор метода ни к одному из классов Blah :: *. Это происходит, даже если я удаляю вызов make_immutable для классов. Я думал, что ролевое приложение было сделано полностью во время выполнения, и поэтому, хотя классы Blah :: * загружаются до Blah, модификатор все еще должен применяться?

Я ищу исправление или альтернативный способ ведения дел. На данный момент Blah по сути является абстрактным базовым классом, за исключением модификатора метода, именно поэтому я начал использовать роли - но, может быть, иерархия классов будет лучше? Заранее спасибо.

Ответы [ 2 ]

4 голосов
/ 16 февраля 2010

Ваш порядок вызовов немного странный - почему вы use используете Blah :: A из роли, которая затем применяется к Blah :: A?

Я бы предложил вытащить эти use строки и переместить их туда, где они действительно нужны (в вызывающей (-их) человеке (-ах)). Сначала нужно, чтобы код работал, а после этого, если у вас много строк use, загромождающих всюду, вы можете переместить их в файл включений.

Но нет, в ответ на ваше предположение - приложение роли не выполняется во время выполнения, но в любое время встречается строка with. Если вы use модуль во время компиляции, то этот файл компилируется немедленно, и выполняется строка with (которая затем вынуждает компилировать роль, а затем она запускается). Конечно, вы можете применить роль и во время выполнения (например, см. Apply_all_roles в Moose :: Util ), но это не то, что здесь происходит.

0 голосов
/ 16 февраля 2010

Я думаю, вы просто неправильно понимаете разницу между включением файлов и составом ролей.

Под капотом операторы use просто вызывают require, а затем выводимый оператор пакета import() и заключают все это в блок BEGIN {}.

Он не устанавливает функции как методы мета-класса с Class :: MOP (CMOP). Я не уверен, в чем разница между объявленным и импортированным методом или как CMOP сообщает разницу, но это работает только из-за вызова add_method. Я бы попросил дополнительную информацию у irc.perl.org/#moose, но я забанен. Надеюсь, этот пример расскажет вам, что вам нужно, или даст вам больше информации, чтобы сформулировать лучший вопрос.

package Class;
use Moose;
use Carp qw(carp);

### You have to add the method onto the class.
Class->meta->add_method( 'carp' => \&carp );

around 'carp' => sub { warn "this won't trigger" };

package main;

my $c = Class->new;
$c->carp('foo');

Если возможно, я бы переписал эти пакеты, которые вы use записали, в дружественные к Moose роли, а затем просто попросите текущую роль вызывать новые роли с помощью оператора with. Роли будут обрабатывать модификаторы методов вокруг других предоставленных ролями методов.

...