2009-12-02 5 views
3

Я ищу способ настроить некоторые вспомогательные методы из родительского класса Moose, а не для автономного класса утилиты. Если это возможно, было бы более прозрачным способом добавления Moose сахара в модули, поскольку он не требует явно требующих каких-либо вспомогательных модулей (так как все поступило бы через объявление extends).Есть ли способ использовать Moose :: Exporter из объекта Moose?

Основываясь на example provided in the documentation, это примерно то, что я собираюсь для:

package Parent; 

use Moose; 

Moose::Exporter->setup_import_methods(
    with_meta => [ 'has_rw' ], 
    as_is  => [ 'thing' ], 
    also  => 'Moose', 
); 

sub has_rw { 
    my ($meta, $name, %options) = @_; 
    $meta->add_attribute(
     $name, 
     is => 'rw', 
     %options, 
    ); 
} 

# then later ... 
package Child; 

use Moose; 
extends 'Parent'; 

has 'name'; 
has_rw 'size'; 
thing; 

Однако это не работает:

perl -I. -MChild -wle'$obj = Child->new(size => 1); print $obj->size' 
 
String found where operator expected at Child.pm line 10, near "has_rw 'size'" 
     (Do you need to predeclare has_rw?) 
syntax error at Child.pm line 10, near "has_rw 'size'" 
Bareword "thing" not allowed while "strict subs" in use at Child.pm line 12. 
Compilation failed in require. 
BEGIN failed--compilation aborted. 

PS. Я также попытался переместить магию экспорта в роль (with Role;, а не extends Parent;), но происходят те же ошибки.

ответ

7

Это не поддерживается, и есть веская причина. Класс или Роль - это не то же самое, что и сахарные методы, и на каком-то уровне разные вещи должны быть разными. Если ваша проблема того, чтобы «использовать» пакет Moose + A Пользовательские сахара, то вы можете решить, что просто иметь свой собственный экспорт сахара пакет лосей, а также, кража из вашего примера:

package MySugar; 
use strict; 
use Moose::Exporter; 

Moose::Exporter->setup_import_methods(
    with_meta => [ 'has_rw' ], 
    as_is  => [ 'thing' ], 
    also  => 'Moose', 
); 

sub has_rw { 
    my ($meta, $name, %options) = @_; 
    $meta->add_attribute(
     $name, 
     is => 'rw', 
     %options, 
    ); 
} 

Тогда вы просто говорите:

package MyApp; 
use MySugar; # imports everything from Moose + has_rw and thing  
extends(Parent); 

has_rw 'name'; 
has 'size'; 
thing; 

Как это работает MooseX::POE, а также несколько других пакетов. Я бы поспорил с тем, что extends принесет сахар, как вы предлагаете здесь, потому что класс не является набором функций сахара, и эти два действительно никогда не должны путать.

ОБНОВЛЕНИЕ: Для одновременного использования самого чистого подхода необходимо переработать родительский элемент как роль, применяемую к Moose :: Object.

Тогда мы просто меняем вызов Moose :: Exporter в MySugar выглядеть

Moose::Exporter->setup_import_methods(
    apply_base_class_roles => 'Parent::Methods', 
    with_meta    => ['has_rw'], 
    as_is     => ['thing'], 
    also     => 'Moose', 
); 

Теперь вы можете просто сказать

package MyApp; 
use MySugar; 

has_rw 'name'; 
has 'size'; 
thing; 

package main; 
MyApp->new->something_special; # prints sparkles 

Что я считаю, что последняя деталь вам были желательны.

+0

То, что я искал, состоит в объединении «Parent» и «MySugar» вместе в один класс, так как сахар специально разработан для создания компонентов, определенных в «Parent». Однако это не конец света, чтобы определить их и привести их отдельно. Я просто не хочу отделять их как два отдельных компонента, потому что их нет. Их следует объединить или вообще не принести. – Ether

+0

Yup, Moose :: Экспортер позволит вам объединить вместе. Определение их обоих в одном классе - это плохая идея, на мой взгляд, потому что она объединяет две разные вещи, которые действительно должны быть раздельными. – perigrin

+0

Я обновил ответ, чтобы включить пример совместного использования вместе с использованием рекомендуемого стиля. Если вы хотите больше, чем это, я предлагаю пройти мимо #moose на irc.perl.org или запросить список рассылки Moose по конкретным вопросам. – perigrin

Смежные вопросы