in reply to opinions on the best way to inherit class data

What about a copy constructor? Something like the following might even be inheritable, or set class-based defaults:
package Original; sub new { my $class = shift; my $other = shift; # hash ref, optional my $self = { name => 'the original', rating => 'supreme commander', boots => 'laced to the knee', }; if ($other) { foreach (keys %$other) { $self{$_} = $other->{$_}; } } bless($self, $class); return $self; } sub copy { my $self = shift; return $self->new($self); }
That's untested, and not particularly beautiful. If you wanted to make it robust, keep around an array of valid keys for your class data. It's not guaranteed to handle nested references correctly, and it may fail in certain inheritance solutions.

But it's an idea. perltootc has more interesting ideas.

If you're really interested in inheritance and smart defaults, separate initialization of the hash from the constructor:

sub new { my $class = shift; my $self = _init(@_); # private method bless($self, $class); return $self; } sub _init { my %data = ( name => 'supreme commander two', rank => 'even better', toothbrush => 'purple with sparklies', ); if (@_) { foreach (keys %{ $_[0] }) { $data{$_} = ${$_[0]}->{$_}; # yuck, probably wrong } } return \%data; # reference! } sub copy { my $self = shift; return $self->new($self); # pass this as a hash ref }
And in a subclass:
sub copy { my $self = shift; my $new = __SUPER__->init($self->new($self)); return $new; }
Okay, now that's *officially* ugly. Just like a real OO language should be.

Replies are listed 'Best First'.
RE: Re: opinions on the best way to inherit class data
by d_i_r_t_y (Monk) on Aug 23, 2000 at 07:03 UTC
    Thanks for the reply, chromatic.

    i think i was perhaps not clear enough about my definition of 'class data', as opposed to 'class defaults', which i believe your response addresses. my apologies.

    some typical 'class data' for example might be:

    # base class package AbstractMyClass; my $_Class_Count = 0; sub new { my $class = shift; my $this = bless( {}, $class ); ref($this) && $_Class_Count++; return $this; } package MyClass; @MyClass::ISA = ('AbstractMyClass'); sub new { my $class = shift; my $this = $class::SUPER->new( @_ ); # this class' init... return $this; }

    if i were to use the code...

    use AbstractMyClass; use MyClass; my $amc = new AbstractMyClass (); my $mc = new MyClass ();

    ...$AbstractMyClass::_Class_Count would be 2, whereas i would have really liked $AbstractMyClass::_Class_Count to be 1, and $MyClass::_Class_Count to be 1. Probably a bad example of the essence of my original question, but nevertheless illustrative of what i am terming 'class data'. thanks, matt aka d_i_r_t_y, since 'zero cool' was taken... ;-)

      Oh, that's what you mean! Here's a sneaky way to do it:
      #!/usr/bin/perl -w use strict; package Superclass; use vars qw ( $AUTOLOAD ); my $classdata = qq| { my \$self = shift; my \$invocations = 0; sub _increase { \$invocations++; } sub number { return \$invocations; } }|; sub new { my $class = shift; if ($class ne __PACKAGE__) { # he he he eval qq|package $class; $classdata |; } my $self = {}; bless($self, $class); $self->_increase(); return $self; } eval $classdata; package Subclass; use vars qw ( @ISA ); @ISA = qw ( Superclass ); package main; print Superclass->number(); my $one = Superclass->new(); print $one->number(); print Subclass->number(); my $two = Subclass->new(); print $two->number();
      If your superclass is in a different module, you can play around with the import subroutine and do it a bit more cleanly.

      This technique has the unfortunate effect of making Subclass->number() return 1 before you create any instance of Subclass. (Inheritance... oh well.)