ऐसा लगता है कि MooseX::Role::Parameterized तरह चाल करना होगा:
साधारण भूमिकाओं की आवश्यकता हो सकती है कि अपने उपभोक्ताओं विधि के नाम की एक विशेष सूची है। चूंकि पैरामीटरयुक्त भूमिकाओं के उपभोक्ता तक सीधे पहुंच है, इसलिए आप इसका निरीक्षण कर सकते हैं और उपभोक्ता आपकी आवश्यकताओं को पूरा नहीं करते हैं तो त्रुटियों को फेंक सकते हैं। (link)
भूमिका विशेषज्ञता का विवरण वर्ग से बढ़ाया गया है; इसे किसी भी पैरामीटर को पास करने की आवश्यकता नहीं है, जिसे यह जानने के लिए आवश्यक है कि भूमिका पारित करने के लिए पैरामीटर (लपेटने के लिए फ़ील्ड की सूची) क्या है। एकमात्र कुंजी यह है कि भूमिका के बाद उपयोग की जानी चाहिए, प्रासंगिक गुण वर्ग पर परिभाषित किए गए हैं।
इसलिए, भस्म वर्ग और भूमिका बन इतनी तरह परिभाषित:
package My::Foo;
use Moose;
my @fields = qw(attr1 attr2);
has \@fields => (
is => 'rw', # ...
);
has 'fields' => (
is => 'bare', isa => 'ArrayRef[Str]',
default => sub { \@fields },
);
with 'My::Role::X' => {};
1;
package My::Role::X;
use MooseX::Role::Parameterized;
role {
my $p = shift;
my %args = @_;
# this should be a Moose::Meta::Class object
my $target_meta = $args{consumer};
# get Class::MOP::Attribute object out of the metaclass
my $fields_attr = $target_meta->find_attribute_by_name('fields');
# extract the value of this attribute - should be a coderef
my $fields_to_modify = $fields_attr->default;
# evaluate the coderef to get the arrayref
$fields_to_modify = &$fields_to_modify if ref $fields_to_modify eq 'CODE';
around $_ => sub {
# ...
} for @$fields_to_modify;
};
1;
परिशिष्ट: मैं ने पाया है कि यदि एक पैरामिट्रीकृत भूमिका एक और पैरामिट्रीकृत भूमिका है, तो $target_meta
नेस्टेड भूमिका में खपत वास्तव में उपभोग वर्ग (आईएसए Moose::Meta::Class
) के मेटा-क्लास की बजाय मूल भूमिका (आईएसए MooseX::Role::Parameterized::Meta::Role::Parameterized
) की मेटा-क्लास होगी। उचित मेटा-क्लास व्युत्पन्न होने के लिए, आपको इसे पैरामीटर के रूप में स्पष्ट रूप से पास करने की आवश्यकता है। मैं एक "सबसे अच्छा अभ्यास" टेम्पलेट के रूप में मेरे सभी पैरामिट्रीकृत भूमिकाओं को यह जोड़ लिया है:
package MyApp::Role::SomeRole;
use MooseX::Role::Parameterized;
# because we are used by an earlier role, meta is not actually the meta of the
# consumer, but of the higher-level parameterized role.
parameter metaclass => (
is => 'ro', isa => 'Moose::Meta::Class',
required => 1,
);
# ... other parameters here...
role {
my $params = shift;
my %args = @_;
# isa a Moose::Meta::Class
my $meta = $params->metaclass;
# class name of what is consuming us, om nom nom
my $consumer = $meta->name;
# ... code here...
}; # end role
no Moose::Role;
1;
परिशिष्ट 2: मैं आगे पता चला है कि भूमिका एक वस्तु दृष्टान्त करने के लिए लागू किया जा रहा है अगर, के रूप में एक वर्ग के लिए विरोध किया, तो भूमिका में $target_meta
वास्तव में वस्तु के वर्ग उपभोक्ता कर हो जाएगा:
package main;
use My::Foo;
use Moose::Util;
my $foo = My::Foo->new;
Moose::Util::apply_all_roles($foo, MyApp::Role::SomeRole, { parameter => 'value' });
package MyApp::Role::SomeRole;
use MooseX::Role::Parameterized;
# ... use same code as above (in addendum 1):
role {
my $meta = $args{consumer};
my $consumer = $meta->name; # fail! My::Foo does not implement the 'name' method
इसलिए, इस कोड के लिए आवश्यक है जब निकालने पैरामीटरयुक्त भूमिका की शुरुआत में मेटा-क्लास:
role {
my $params = shift;
my %args = @_;
# could be a Moose::Meta::Class, or the object consuming us
my $meta = $args{consumer};
$meta = $meta->meta if not $meta->isa('Moose::Meta::Class'); # <-- important!
यह मॉड्यूल के लिए लिखे गए कार्यों में से एक है। – perigrin
नोट: मैं अब उपर्युक्त "सर्वोत्तम अभ्यास" पर विचार नहीं करता हूं, और वास्तव में एमएक्सआरपी के इस (एबी) उपयोग को दोबारा प्रतिक्रिया देता हूं। आईएमएचओ अगर आपको भूमिका के भीतर से '$ मेटा' तक पहुंचने की ज़रूरत है, तो आपके डिजाइन में कुछ बदबूदार है। – Ether