~~David~~ has asked for the wisdom of the Perl Monks concerning the following question:

I am reading a file and want to automatically generate accessors based on the fields in this file. I start out generating a small subset of accessors that I need to read status and error stuff, but then I want to add more accessors as I read the file. So far, I have not been able to accomplish this. No error messages are generated, but when I try to call an accessor on a dynamically generated accessor, I get the following error:Can't locate object method "mymethod" via package "mypackage" Here is my code where I pass a key, value pair from the file into a sub called kv that is supposed to generate methods:
package KLARF; use strict; use warnings; use base qw(Class::Accessor); # set up initial accessors KLARF->mk_accessors( qw( state debug current_list ) ); # overload state accessor to print current state in debug mode sub state { my $self = shift; if ( @_ ){ $self->{state} = shift; print "$self->{state}\n" if $self->{debug}; return $self->{state}; } else { print "$self->{state}\n" if $self->{debug}; return $self->{state}; } } sub kv { my $self = shift; my $key = shift; my $value = shift; $key = lc $key; if ( $self->{state} eq 'RECORD' ){ $value =~ s/\"//g; chomp $value; } if ( $self->{state} eq 'FIELD' ){ $value =~ s/\"//g; $value =~ s/\s//g; my @values = split /,/, $value; $value = \@values; } if ( $self->{debug} ){ print uc "Key is $key, Value is $value\ +n"}; $self->{$key} = $value; KLARF->make_accessor( $key ); # this doesn't seem to work??? }
I have done this already using Moose, but I can't use Moose for this application. Maybe this is not even possible using Class::Accessor, I couldn't find anything saying it was or wasn't. Thanks for any help.

Replies are listed 'Best First'.
Re: Dynamic Method Generation Using Class::Accessor
by ikegami (Patriarch) on Aug 13, 2009 at 15:27 UTC
    Looking at the source, I don't see anything that cares when mk_accessors is called. I also don't have any problems as desired.
    package KLARF; use strict; use warnings; use Class::Accessor qw( ); our @ISA = 'Class::Accessor'; __PACKAGE__->mk_accessors(qw( foo )); sub more { __PACKAGE__->mk_accessors(qw( bar )); } 1;
    $ perl -wle' use KLARF; KLARF::more(); my $o = KLARF->new(); $o->foo("abc"); print $o->foo(); $o->bar("def"); print $o->bar(); ' abc def

    By the way, using __PACKAGE__ is usually deemed wiser than hardcoding the package name everywhere.

Re: Dynamic Method Generation Using Class::Accessor
by moritz (Cardinal) on Aug 13, 2009 at 15:35 UTC
    The following example forks for me:
    package KLARF; use strict; use warnings; use base qw(Class::Accessor); my $s = 'foo'; my $x = bless {}; $x->{$s} = 'bar'; KLARF->mk_accessors($s); print $x->foo(), "\n";

    So there doesn't seem to be a problem with generating the accessors at run time.

    Maybe $key doesn't contain what you think it does? Since you only print out the upper cased version, maybe the case is wrong? Or it could contain non-printable characters.

    Since you neither show nor input data nor how the methods are called it's a bit hard to find out what's really going on.

    Anyway, do you really think you need these accessors? generating identical methods based on input data seems like not a really great idea, a hash or a generic accessor might be a better idea.

      Thanks for the input. I am trying to learn here, so could you elaborate on your comment about it not being a good idea to create the accessors. Would you recommend something like my $foo = $s->generic('foo'); Why is that beneficial (speed, maintainability?)? Thanks, David
        If you install methods for each new attribute, you install them in symbol table, which is shared among all objects.

        So whenever you install an accessor method for an object, all other objects get that too - although it doesn't make sense for them to have one.

        It also means that if you have a long running process, you might gather many methods which once were useful, but don't make sense anymore.

        Also consider the case where somebody might want to subclass your class, and can't know at the time of writing which methods your class will have - that's kinda painful.