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
>> ==========================*/
>>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.