http://qs321.pair.com?node_id=869460

sundialsvc4 has asked for the wisdom of the Perl Monks concerning the following question:

Okay, my mind went blank, much too late last night (and not for bottled reasons).   I coded what I intended to be a package with an inherited constructor, but the inherited routine was never called.   The code looked like this: (Perl 5.10.0)

package Foo; use base qw/Bar/; sub new { my $class = shift; my $self = $class->SUPER::new(@_); bless $self, $class; return $self; } ... (in main) $bletch = Foo->new; print ref($bletch); # gives "Foo"

Edit:   Typo in constructor-call removed.

When I set croak calls and other things in the supposedly-inherited routine (in Foo), they never went off.   But the routine in Bar did.  

Furthermore:   other methods defined in Foo (but not in Bar...) were available.   So, it’s not like Perl didn’t know what package I was talking to ... it’s just that a routine defined in the child-class was ignored in favor of the parent, and I don’t know quite why.

Sure, I could define an initialize() method and call that from the constructor, but I want to understand what eluded my then-befuzzed brain.

Have I been this-quickly and so-utterly spoiled by Moose?   :-)

Replies are listed 'Best First'.
Re: Duh. What am I missing about inherited constructors?
by kcott (Archbishop) on Nov 04, 2010 at 13:51 UTC

    Your problem is Foo::new which should be Foo->new

    With use warnings; you'll get: Can't call method "SUPER::new" on an undefined value at...

    -- Ken

Re: Duh. What am I missing about inherited constructors?
by JavaFan (Canon) on Nov 04, 2010 at 13:51 UTC
    You're calling Foo::new as a sub, without arguments. Then $class is undef. That should cause the sub to die.

    If I change Foo::new to Foo->new it works as I expect.

    But you aren't inheriting any constructors here.

Re: Duh. What am I missing about inherited constructors?
by Anonymous Monk on Nov 04, 2010 at 13:47 UTC
    Not sure I understand your problem description, but perhaps you meant Foo->new ?

    Foo::new doesn't pass a class parameter...

Re: Duh. What am I missing about inherited constructors?
by hossman (Prior) on Nov 04, 2010 at 18:18 UTC

    Ignoring the mistake which you have since fixed, posting a runnable example of your problem is invaluable. At best we can extrapolate what we *thin* you code might look like in a runable form, and try that -- in my case, it works fine...

    #!/bin/perl -l use warnings; use strict; package Bar; sub new { print STDERR "Bar'ed"; my $class = shift; my $self = {}; bless $self, $class; } package Foo; use base qw/Bar/; sub new { print STDERR "Foo'ed"; my $class = shift; my $self = $class->SUPER::new(@_); bless $self, $class; return $self; } my $foo = Foo->new; print ref($foo); # gives "Foo"

    ...Produces...

    hossman@bester:~$ perl ~/tmp/monk.pl Foo'ed Bar'ed Foo
Re: Duh. What am I missing about inherited constructors?
by juster (Friar) on Nov 04, 2010 at 20:05 UTC
    When I set croak calls and other things in the supposedly-inherited routine (in Foo), they never went off. But the routine in Bar did.

    This is confusing. Some example code would help tremendously. Do you mean the routine is defined in the Foo package? Or do you mean a routine defined in Bar? Methods in Foo are not inherited by Bar. Calling a method on a Foo object not defined in Foo but defined in the Bar package should correctly "go off" in the Bar routine.

    Furthermore: other methods defined in Foo (but not in Bar...) were available. So, it’s not like Perl didn’t know what package I was talking to ... it’s just that a routine defined in the child-class was ignored in favor of the parent, and I don’t know quite why.

    I think you have the child-parent relationship backwards. Methods defined in the Foo package should indeed be available for a Foo object but not for a Bar object. Foo is the child class and Bar is the parent.

    The following is a trivial pet-peeve of mine. You don't need to bless $self, $class inside Foo::new because Bar::new should already have blessed it. The first parameter to Bar::new will be "Foo".

Re: Duh. What am I missing about inherited constructors?
by sundialsvc4 (Abbot) on Nov 05, 2010 at 01:07 UTC

    Okay, let’s just close this one out as “one of those things.”   Probably, I must have overlooked something, and it isn’t reasonable to think of it as a “real bug.”

    Lesson:   go home at a reasonable hour.

Re: Duh. What am I missing about inherited constructors?
by sundialsvc4 (Abbot) on Nov 04, 2010 at 17:39 UTC

    I told you my brain was befuzzed.   The :: should have been -> in that posting.

    I expected that the call to new would wind-up executing the code in Foo which would, by means of $class->SUPER::, invoke the one in Bar...

      I expected that the call to new would wind-up executing the code in Foo which would, by means of $class->SUPER::, invoke the one in Bar...
      But it does. What makes you think it doesn't? I cannot deduce the problem from your code snippet.
      use 5.010; package Bar; sub new { say "Bar!"; []; } package Foo; use base qw/Bar/; sub new { my $class = shift; say "Foo!"; my $self = $class->SUPER::new(@_); bless $self, $class; return $self; } package main; my $bletch = Foo->new; say ref($bletch); __END__ Foo! Bar! Foo