hash reference to object methods

B

Ben Jones

Hi,

I'm farily new to oo perl, and wondered if either someone could help me with
the following problem, or suggest a less ugly way of doing it...

I am creating an object whose attributes are loaded from various data
sources. Various groups of attributes are loaded from specific sources,
but I don't want the overhead of loading attributes when client code hasn't
asked for it yet, and might not ever. I didn't want to write an accessor
for each, so I thought I's use AUTOLOAD. My AUTOLOAD method checks to see
if the hash attribute exists, and if it doesn't, calls a private method to
load the correct one. The first solution I thought of to accomplish this
was to use a hash, with the attribute sought being the key, and the value
being a ref to the apporpriate method. So in non oo, something like this:

sub _load_attrs {
my $attr = shift;
my %attr_lookup = ( 'attr1' => \&method1,
'attr2 => \&method2);
}

....etc

But this confuses me in oo - how do I do the refs, and how do I deference
them?

My initial thought would be:

sub _load_attrs {
my ($self, $attr) = @_;
my %attr_lookup = ( 'attr1' => \$self->_load_group1,
'attr2' => \$self->_load_group2);
}

....etc

Is that right? If it is, how do I deference the methods? Or is this
incredibly wrongheaded?
 
U

Uri Guttman

BJ> Hi, I'm farily new to oo perl, and wondered if either someone
BJ> could help me with the following problem, or suggest a less ugly
BJ> way of doing it...

just as a contrast to the doofus thread, note the good subject, good
background info and a respectful question.

BJ> I am creating an object whose attributes are loaded from various
BJ> data sources. Various groups of attributes are loaded from
BJ> specific sources, but I don't want the overhead of loading
BJ> attributes when client code hasn't asked for it yet, and might not
BJ> ever. I didn't want to write an accessor for each, so I thought
BJ> I's use AUTOLOAD. My AUTOLOAD method checks to see if the hash
BJ> attribute exists, and if it doesn't, calls a private method to
BJ> load the correct one. The first solution I thought of to
BJ> accomplish this was to use a hash, with the attribute sought being
BJ> the key, and the value being a ref to the apporpriate method. So
BJ> in non oo, something like this:

this sounds like a fine idea. but the first question is how much work is
it really to get all those attributes at construction time? if they
require slow things like file reads or DB access or page fetches and you
may never use them, your idea makes sense.

BJ> sub _load_attrs {
BJ> my $attr = shift;
BJ> my %attr_lookup = ( 'attr1' => \&method1,
BJ> 'attr2 => \&method2);
BJ> }

for methods you can just use the method name and call them.

my %attr_lookup = ( 'attr1' => 'method1'
'attr2 => 'method2');


my $method = $attr_lookup{ $attr } ;

$self->$method() ;

that is called late binding (among other names). one of perl's nice OO
features is generating method calls on the fly. note that this is NOT
the same as symbolic references which are evil.

now how you handle the AUTOLOAD will also make a difference. using
AUTOLOAD to access attributes will be slow. it should autogenerate
accessor methods on demand as well as initializing the attributes. then
the next time the accessor is called, it will have an installed method
and be initialized.

a simple (untested) version is this:

sub AUTOLOAD {

my $self = shift ;

my $attr = $AUTOLOAD ;
$attr =~ s/.*://;

*{$attr} = sub {
$_[0]->{$attr} = $_[1] if @_ > 1 ;
return $_[0]->{$attr}
} ;

goto &{$attr} ;
}

add your call to the initializer method before the magic goto call at
the end.

note how an intelligent question gets an intelligent answer with
examples and more. too bad doofus will never get help here again because
he got killfiled by too many.

uri
 
B

Ben Jones

Uri said:
BJ> Hi, I'm farily new to oo perl, and wondered if either someone
BJ> could help me with the following problem, or suggest a less ugly
BJ> way of doing it...

just as a contrast to the doofus thread, note the good subject, good
background info and a respectful question.

Although in my case a seemingly well-formed question is partly a lucky
accident ;)
this sounds like a fine idea. but the first question is how much work is
it really to get all those attributes at construction time? if they
require slow things like file reads or DB access or page fetches and you
may never use them, your idea makes sense.

A *lot* of work, for a particular class of attributes, that are loaded from
a particularly slow script, accessing a particularly slow database, neither
of which I have much control over. And I have reason to expect that not
every user of the module will care to use them. In fact the script I was
writing this module for definitely won't always. Client code that chooses
to access them gets an overhead measured in seconds...
for methods you can just use the method name and call them.

my %attr_lookup = ( 'attr1' => 'method1'
'attr2 => 'method2');


my $method = $attr_lookup{ $attr } ;

$self->$method() ;

that is called late binding (among other names). one of perl's nice OO
features is generating method calls on the fly. note that this is NOT
the same as symbolic references which are evil.

Of course! As always with elegant solutions, it looks so damned obvious
now.

note how an intelligent question gets an intelligent answer with
examples and more.

And may I note an extremely speedy response. Thanks for your help, you've
saved a good deal of head-scratching.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top