in reply to OO - problem with inheritance

This is definitely a hangover from Java, but whenever I do inheritance in Perl, I write the code so that the parent constructor is called from the child class' constructor. In Java, every time you extend a class, whether you say so explicitly or not, you instantiate everything all the way up the hierarchy up to java.lang.Object.

In Perl I often see people use inheritance with methods only; that is, they inherit the behavior but not the data. To me, both are necessary for object oriented inheritance.

My suggestion is to write the general constructor in the base class with a default value for the parameter checking. If a subclass needs something different, it calls the base class constructor with the proper parameters. In Java, this is super(params), in Perl the child constructor would say:

  my ($class, $whatever) = @_;
  my %params = (); # new params to use instead of parent's params
  my $this = new base_class(%params); # create a new parent
  bless($this, $class); # rebless into the current package

Replies are listed 'Best First'.
Re: super(params)
by IlyaM (Parson) on Jan 15, 2002 at 19:12 UTC
    It is better to rewrite your code as:
    my ($class, $whatever) = @_; my %params = (); # new params to use instead of parent's params my $self = $class->SUPER::new(%params); # create a new parent bless($self, $class); # rebless into the current package
    Note that this variant doesn't hardcode baseclass name.

    BTW I strongly advice against using $this in Perl code. Most Perl programmers are too get used to $self. I recall than in the company where I worked until recenly we have one programmer (who was Java fan but liked Perl too) who used $this in his code. It was big PITA for everybody who had to edit that code. Fingers just type $self and only later you release (when you see Global symbol "$self" requires explicit package name) that it should be $this. After several such accidents we just told him that $this is forbidden :)

    Anyway there is nothing wrong in using same constructor in all classes as long as it deffers object initialization to some methods which are overriden in subclasses. Actually it is very common practice and not only in Perl.

    --
    Ilya Martynov (http://martynov.org/)

      And, if you need to call multiple parental classes, there's NEXT, e.g.: $class->NEXT::new(%params).

      As for $this vs. $self -- it seems that should be a local style standard, and not a global Perl-wide proscription. So long as it's consistent inside a given project, and easily s///able, use $dohickey, $The_Monster, or $Frank. TMTOWTNI.

      -- Frag.
      --
      "It's beat time, it's hop time, it's monk time!"

      $class->SUPER::new(%params);
      Okay point taken. However this business with '$self' is truly not something that ought to be mandated across all projects, because while it may be a common idiom in the Perl community (most likely due to the nice phrase 'my $self'), for those of us that work in multiple OO languages it is not the norm. I routinely have to switch between the two, and from experience I declare: it's no big whoop.

Re: super(params)
by frag (Hermit) on Jan 15, 2002 at 23:19 UTC
    There's at least a potential hazard in this approach: what if your parent constructor does parameter checking, and is more restrictive than your subclass? Then the above would be dangerous -- you'd lose the values in %params -- and you'd want to do something like:
    my ($class, $whatever) = @_; my %params = (); # new params to use instead of parent's params my $this = new base_class; # create a new parent, and # let it set its own defaults # clobber the base_class' defaults: while (my ($k,$v) = each %params) { $this->{$k} = $v; } bless($this, $class); # re-bless into the current package
    Ugly and hypothetical, but something to be aware of.

    On second thought, better still: always make any parameter checking in the constructors throw a fatal error. Note such errors in development and change the parent's constructor to play nice.

    -- Frag.
    --
    "It's beat time, it's hop time, it's monk time!"