Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make an object in my parent class but bless it into my child class in Perl?

I have two classes: a base class, Foo::Base and a derived class, Foo::Base::Sub. I want to have Foo::Base::Sub do some type and data checking on the constructor`s argument--a hash--before blessing it. I've tried overriding Foo::Base->new's constructor, doing the checks and then calling Foo::Base->new (since the code would be exactly the same):

package Foo::Base::Sub;

sub new {
    ...check argument's type and data...
    Foo::Base->new(%my_hash)
}

The problem is that by calling Foo::Base's constructor, the hash will now be blessed as a Foo::Base object and not a Foo::Base::Sub object. The obvious solution is simply to put the code from Foo::Base::new into Foo::Base::Sub::new but then I'm repeating code. The other thing is that Foo::Base is not mine--thus I'd like to avoid having to modify it after the module has loaded or forking it unnecessarily.

It seems to me that this problem must have come up before and so there must be a canonical solution. Moreover, it really touches on type coercion which is generally not an issue Perl.

So is there a simple modification or am I going about this the wrong way?

like image 711
gvkv Avatar asked Dec 07 '22 04:12

gvkv


1 Answers

A standard Perl idiom is to use SUPER to call up the inheritance chain:

@Foo::Base::Sub::ISA = qw(Foo::Base);

sub new {
    my $package = shift;

    my $self = $package->SUPER::new();

    # Other subconstructor stuff here

    return $self;
}

As noted in the comments, Foo::Base's constructor must use the two-argument form of bless:

sub new {
    my $package = shift;

    my $self = bless {}, $package;

    # Other superconstructor stuff here

    return $self;
}

When the superclass' constructor is called, $package will be the subclass.

like image 197
Commodore Jaeger Avatar answered Apr 29 '23 11:04

Commodore Jaeger