Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re^2: Enumerating all attributes of a Moo object

by McA (Curate)
on Jul 09, 2013 at 07:20 UTC ( #1043254=note: print w/ replies, xml ) Need Help??


in reply to Re: Enumerating all attributes of a Moo object
in thread Enumerating all attributes of a Moo object

Hi tobyink,

thank you for your answer. The comments above and what you showed me let me think again about what I wanted to do:

I want to implement a factory class generating Moo-objects. IMHO a factory class IS tightly coupled with the objects it creates. I wanted to avoid to explicitly enumerate every attribute in the code for initialisation of the created object.

Do you think that the usage of the mentioned "introspection"-method is a good way to achieve that? Or should I use a different design?

By the way: With 'attributes' I thought of all setters related to the attributes declared via 'has', that means all names used for the initialisation hash for method 'new'. Is there a common wording for that?

Best regards
McA


Comment on Re^2: Enumerating all attributes of a Moo object
Re^3: Enumerating all attributes of a Moo object
by tobyink (Abbot) on Jul 09, 2013 at 08:27 UTC

    What you need to bear in mind, is that an attribute could have several different names associated with it. Consider:

    use v5.14; package Foo { use Moo; has foo1 => ( is => "rw", init_arg => "foo2", reader => "foo3", writer => "foo4", ); } # Create an object, setting the attribute... my $obj = Foo->new(foo2 => 40); # Increment the value... $obj->foo4( $obj->foo3 + 1 ); # Or cheat and access the hashref directly... $obj->{foo1}++; # Print the value of the attribute... say $obj->foo3;

    Moo does have all this data buried away, but you may be better off using Moose or Mouse which provide documented, public APIs for all this attribute introspection stuff.

    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re^3: Enumerating all attributes of a Moo object
by tobyink (Abbot) on Jul 09, 2013 at 08:39 UTC

    I'll also point out a technique you could use. Instead of FooFactory introspecting class Foo, you could have class Foo pass FooFactory all the information it needs. One simple way to do that is write a wrapper for has...

    #!/usr/bin/env perl use v5.14; use Data::Dumper; package FooFactory { use Moo; has name => (is => "ro", required => 1); our @known_attributes; sub build_foo { my $self = shift; my %params = @_; my %attrs; for (@known_attributes) { $attrs{$_} = $params{$_} if exists $params{$_}; } 'Foo'->new(%attrs, maker => $self); } } package Foo { use Moo; sub my_has { my ($attr, %spec) = @_; # Inform FooFactory of the new attribute # Note we're ignoring init_arg for this simple example. push @FooFactory::known_attributes, $attr; has($attr, %spec); } my_has foo => (is => "ro"); my_has bar => (is => "ro"); my_has baz => (is => "ro"); my_has maker => (is => "ro"); } my $factory = 'FooFactory'->new(name => "Acme Inc"); my $obj = $factory->build_foo(bar => 42); print Dumper($obj);
    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name

      Hi tobyink,

      another "Thank you" and ++ for that.

      Do you think this would be "good" design?

      Refering to the warning post above, don't you have to react on the %spec in the my_has-method, so that you really grab the accessor-name for the initialisation?

      Best regards
      McA

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1043254]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (3)
As of 2014-10-26 00:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (149 votes), past polls