Re: Moose Question
[email protected] (Paul Driver)
| Newsgroups | perl.moose |
|---|---|
| Message-ID | <[email protected]> |
Chris,
If you want to add generated methods to the class, it's __PACKAGE__-
>meta->add_method(foobar => sub { print "Foo, bar!\n" }); I don't
think you want to do this in BUILD though - just at class compile
time. I do this a lot when I have a bunch of similar methods and
don't want to repeat myself.
If you want to add methods to a particular instance ONLY, the thing
to do is to create an anonymous subclass and rebless your instance to
that subclass, and add the methods to the subclass.
Some example code - at BUILD time, add a method named $word that does
say $word for every word passed into the constructor.
---
use feature q(say);
package Speaker;
use Moose;
has words => (
is => 'ro',
isa => 'ArrayRef[Str]',
predicate => 'has_words',
);
# All Speakers know how to say bar
sub bar {
say 'bar';
}
sub BUILD {
my ($self, $args) = @_;
if ($self->has_words) {
my %methods = map {
my $word = $_;
($word => sub { say $word})
} @{$self->words};
$self->meta->create_anon_class(
superclasses => [__PACKAGE__],
methods => \%methods,
)->rebless_instance($self);
}
}
package main;
my $a = Speaker->new;
my $b = Speaker->new(words => [qw(baz qux)]);
$a->bar; # => "Bar"
$b->bar; # => "Bar"
$b->qux; # => "Qux"
say "A" if $a->isa('Speaker'); # => "A"
say "B" if $b->isa('Speaker'); # => "B"
$a->qux; # Can't locate method "qux" via class "Speaker"
----
On Mar 19, 2008, at 4:22 PM, Christopher Brown wrote:
> Dave,
>
> Sorry for taking so long to thank you for your reply. Thanks. On
> further
> t, it was a silly question, using a plain old method is obviously the
> solution.
>
> I do have follow-up questions, though. Suppose I want to generate
> those
> plain old methods dynamically. Is there a simple, moose way to do
> this in
> the BUILD subroutine. On e way to accomplish this is to assign an
> anonymous subroutine to a glob. Like this:
>
> package My::App;
>
> use Moose;
> has name => ( is => 'rw', isa=>'Str' );
>
> sub BUILD {
> **__PACKAGE__::method = sub { print "hello world\n"; } ;*
> }
>
> package main;
> my $app = My::App->new( { name => 'Moose' } );
> $app->method;
>
>
> But I don't want to do that. I want to do it the Moose way.
>
> I can hear you ask, but why would you want to do that? Well
> suppose, I
> create an object that wraps a query. If I can iterate over the
> record set I
> can replace the data slot with the new record and still named
> methods that
> act as accessors to the record. This beats the snot out of trying to
> instanciate a row object for each record.
>
> Thanks in Advance,
>
> Chris
>
>
>
>
>
> On Wed, Mar 12, 2008 at 2:41 PM, Dave Rolsky <[email protected]> wrote:
>
>> On Wed, 12 Mar 2008, Christopher Brown wrote:
>>
>>> Despite the 'lazy' evaluation, it appears as if the attribute
>>> value is
>> being
>>> cached instead of being re-evaluated when the accessor is being
>>> called.
>>
>> Lazy just means "don't generate the attribute from the default sub
>> until
>> the _first_ time it is requested". It's still cached.
>>
>> If you want to return a different value each time then you just
>> want a
>> plain old method, not an attribute.
>>
>>
>> -dave
>>
>> /*==========================
>> VegGuide.Org
>> Your guide to all that's veg
>> ==========================*/
>>