Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

Re: Your favorite objects NOT of the hashref phylum (array w/ consts)

by tye (Sage)
on Mar 23, 2006 at 20:43 UTC ( #538858=note: print w/replies, xml ) Need Help??

in reply to Your favorite objects NOT of the hashref phylum

I prefer a ref to a blessed array with constants noting which member data is stored at which array index:

... my $offset; BEGIN { $offset= 0; # Or BaseClass->_GetMaxOffset(); for my $attrib ( qw/ foo bar baz / ) { eval "sub _$attrib() { $offset }; 1" or die $@; $offset++; } } sub _GetMaxOffset { $offset } # Example method sub Foo { my $me= shift @_; my $old= $me->[_foo]; if( @_ ) { my $new= shift @_; # validate here $me->[_foo]= $new; } return $old; }

You can get compile-time catching of mispelt attribute names, faster and more compact objects, minimal increase in code complexity.

Updated: Dropped the extra "my" inside the BEGIN block as pointed out by vhold (Thanks!).

- tye        

Replies are listed 'Best First'.
Re^2: Your favorite objects NOT of the hashref phylum (array w/ consts)
by nothingmuch (Priest) on Mar 26, 2006 at 11:28 UTC
    For compile time catching of typos in attrs when using hashes as the internal representation use the fields module.

    In perl 5.8 it's based on pseudohashes, which are a bit like mapping strings into arrays, except they use hash syntax. But everyone knows that pseudohashes suck ;-)

    In perl 5.9 fields uses Hash::Util and locks the hash for runtime checks, and also performs the same compile time checks, so you get the benefits of fields without the insanity of pseudohashes.

    The way you use it is:

    use fields qw/attr1 attr2/; sub new { # ... my __PACKAGE__ $self = fields::new($pkg); # construct using fields +::new $self->{attr1} = "foo"; # ok $self->{attttr2} = "bar"; # compile time error } sub some_method { my __PACKAGE__ $self = shift; # use __PACKAGE__ or any class name +to tell perl what class $self is $self->{foo}; # because we told it to make compile time checks bas +ed on __PACKAGE__'s fields this will be checked at compile time }
    But this still doesn't let you encapsulate the properties in subroutines that you can override.
    zz zZ Z Z #!perl
Re^2: Your favorite objects NOT of the hashref phylum (array w/ consts)
by vhold (Beadle) on Mar 25, 2006 at 00:33 UTC
    This is my favorite approach, and It's good that you show the extra hoop you have to jump through to support inheritence, but watch out that you did "my $offset" twice, making _GaxMaxOffset always return undef.
Re^2: Your favorite objects NOT of the hashref phylum (array w/ consts)
by nothingmuch (Priest) on Mar 26, 2006 at 08:27 UTC
    How do you handle multiple inheritance?

    Perhaps with the Moose module you can write a metaclass that uses named syntax for attributes, but compiles the offsets as late as possible in a way that takes care of MI, much like $any_static_language's vtables are compiled.

    zz zZ Z Z #!perl

      I strongly dislike class-making frameworks that everyone and their dog wants to bolt onto the side of Perl. So I'm not going to be writing any plug-ins for one. I've never seen any significant value in any of them and most of them look quite prone to break things due to ETOOMUCHMAGIC (and I've seen several actually break things), so I'm quite happy to avoid all of them completely. I don't find it particularly challenging to implement reasonable classes using just Perl 5 and I like that understanding my code doesn't require understanding some extra framework first.

      I try to (and succeed at) avoiding inheritance in most cases, especially in Perl. Inheriting interfaces (aka pure-virtual classes) is a fine thing. Inheriting from a class that contains code is very often not the best solution and I (and many other experienced developers) know all too well how inheritance binds very tightly and can lead to brittle designs that become a burden.

      So, if Perl had interfaces I might write Perl classes that inherit from more than one set of interfaces. Since Perl doesn't have (non-trivial) interfaces, I only rarely use inheritance in Perl and I have never been tempted to use multiple inheritance in Perl.

      If I had new-fangled near-inheritance tools (traits, mix-ins, or whatever you want to call them), I'd probably make use of those more often.

      I find that I'm more successful in the long run when I bend my approach to a problem to fit the language that I'm solving it in, rather than trying to bend the language to fit my first choice of approach. So I write Perl 5 classes in Perl 5 OO and easily resist the urge to try to turn Perl into my ideal OO framework, even though Perl often appears to make it somewhat easy for you to bend it.

      - tye        

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (8)
As of 2019-09-18 07:54 GMT
Find Nodes?
    Voting Booth?
    The room is dark, and your next move is ...

    Results (223 votes). Check out past polls.