hash reference to object methods

Discussion in 'Perl Misc' started by Ben Jones, Aug 12, 2003.

  1. Ben Jones

    Ben Jones Guest

    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?
     
    Ben Jones, Aug 12, 2003
    #1
    1. Advertising

  2. Ben Jones

    Uri Guttman Guest

    >>>>> "BJ" == Ben Jones <> writes:

    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

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
     
    Uri Guttman, Aug 12, 2003
    #2
    1. Advertising

  3. Ben Jones

    Ben Jones Guest

    Uri Guttman wrote:

    >>>>>> "BJ" == Ben Jones <> writes:

    >
    > 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.

    <rest snipped and saved>

    > 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.
     
    Ben Jones, Aug 12, 2003
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. rp
    Replies:
    1
    Views:
    555
    red floyd
    Nov 10, 2011
  2. Xeno Campanoli
    Replies:
    16
    Views:
    273
    Martin DeMello
    Aug 25, 2005
  3. Pokkai Dokkai
    Replies:
    8
    Views:
    140
    Phrogz
    Nov 18, 2007
  4. Srijayanth Sridhar
    Replies:
    19
    Views:
    640
    David A. Black
    Jul 2, 2008
  5. Kenneth McDonald
    Replies:
    5
    Views:
    343
    Kenneth McDonald
    Sep 26, 2008
Loading...

Share This Page