http://www.perlmonks.org?node_id=178518


in reply to Re: Re: Where/When is OO useful?
in thread Where/When is OO useful?

I go one step further than "fly weight objects". I take a lexical hash for each attribute, and index those with the object. This means you never have to use string literals to access attributes (and hence you get the full benefit of using strict), and you only need one hash query instead of two to access the attribute.

Here's my implementation of the BaseballPlayer::Pitcher class. It's totally independent of the implementation of the BaseballPlayer class (although it could be that you want to mask the constructor - but that's ok because the constructor is part of the API). I call this technique "Inside Out Objects" (people who saw my presentation at YAPC know all about it).

package BaseballPlayer::Pitcher; { use vars '@ISA'; @ISA = 'BaseballPlayer'; my (%ERA, %Strikeouts); sub ERA : lvalue {$ERA {+shift}} sub Strikeouts : lvalue {$Strikeouts {+shift}} sub DESTROY { my $self = shift; delete $ERA {$self}, $Strikeouts {$self} } }

Abigail

Replies are listed 'Best First'.
Re: Re: Where/When is OO useful?
by sauoq (Abbot) on Sep 10, 2002 at 19:42 UTC
    delete $ERA {$self}, $Strikeouts {$self}

    That won't work like you expect it to.

    $ perl -le 'my(%one,%two);$one{k}=1;$two{k}=2;delete $one{k}, $two{k}; + print "one exists" if exists $one{k};print "two exists" if exists $t +wo{k}' two exists

    Nice technique though.

    -sauoq
    "My two cents aren't worth a dime.";
    
Re: Re: Where/When is OO useful?
by Anonymous Monk on Aug 28, 2002 at 03:16 UTC
    Nice. Do you also have recommendations for keeping everything as neat and tidy while adding persistence? I've managed a few simple cases with Storable hooks, but dependencies on the ancestor class beyond just its api seem to be rearing their heads again :-(
      It shouldn't be too hard to write save and restore functions that dump the appropriate values of the hashes.

      And it's real easy to make class level save and restore functions that save/restore *all* the instances of a class.

      However, to do this right, you do need to cooperation of the classes you inherit....

      Abigail

Re: Re: Where/When is OO useful?
by scrottie (Scribe) on Jun 14, 2003 at 09:25 UTC
    Another object idiom: this one, people tell me is aweful. I like it a lot because it overcomes something I hate about Perl: how object instance data requires lots of funny syntax. This syntax makes it tedious to refactor code from a subroutine into a method. Like Abagail's, it uses lexicals to good effect. It requires some glue, but class fields are then normal lexical variables. The object is a blessed hash - but instead of data, the hash holds the methods. The AUTOLOAD glue just dispatches to the correct hash element. The glue sets $self, so it is not necessary to read it off of the argument list manually, should it be needed (for a method call, for example).
    sub new { my $ERA; my $Strikeouts; bless { get_ERA => sub { $ERA }, set_ERA => sub { $ERA = shift }, get_Strikeouts => sub { $Strikeouts }, set_Strikeouts => sub { $Strikeouts = shift }, }, shift(); } sub AUTOLOAD { (my $method) = $AUTOLOAD =~ m/::(.*)$/; return if $method eq 'DESTROY'; our $this = shift; if(! exists $this->{$method}) { my $super = "SUPER::$method"; return $this->$super(@_); } $this->{$method}->(@_); } 1;
    Primary drawbacks are a small speed penalty - but for very small data classes like this, I tend to use rather ordinary blessed arrays, anyway, or psuedohashes, or "use fields" pragmatic module (all about the same thing right now - psuedohashes will be going away I'm told). Code inheritance works - however, fields declared lexically like this aren't inherited. All data is essentially private. I find this just as well - it forces a subclass to use its parents accessors. Finally, you have to be somewhat accustomed to Functional Programming to be used to staring at indenting like that. This is just a brief restatement of the second half of Anonymous Subroutine Objects at PerlDesignPatterns.com. I treat the AUTOLOAD footer as a Wrapper Module, and just use it into my namespace.