Sam
Sam

Reputation: 47

Method not found error when inheriting abstract method in Perl OOP

I have a subclass that calls a method from a superclass. The method in the superclass uses a method that is defined in the superclass as abstract (not really abstract) but implemented in the subclass.

For example:

package BaseClass;

sub new
{

}
sub method1 {

    return someAbstractMethod();
}



sub someAbtsractMethod
{
     die "oops, this is an abstract method that should " . 
         "be implemented in a subclass" ;
}
1;

package SubClass;

sub new
{

}

sub someAbtsractMethod
{
     print "now we implement the asbtract method";
}
1;

Now when I do:

$sub = new SubClass();
$sub->method1();

...it calls the abstract message and I get the specified error message. If I took off the abstract method from the super class and just leave the implementation in the subclass, It does not recognize the method and I get subroutine abstract method not found error.

Upvotes: 2

Views: 1873

Answers (4)

hobbs
hobbs

Reputation: 239811

Your fundamental problem is that you're not using method calls at all. Had you done

sub method1 {
  my $self = shift;
  $self->someAbstractMethod();
}

in the base class (and assuming inheritance was set up properly) then things would work. But when you write someAbstractMethod() that's not a method call, it's a function call, so it's resolved immediately at compile-time, without any regard for polymorphism (what the type of the object is).

Upvotes: 3

iain
iain

Reputation: 21

If you are just starting out with Perl OO dont forget to check out Moose. See also Moose::Manual::Unsweetened for a comparison of Moose with regular Perl 5 OOP style.

Upvotes: 2

daotoad
daotoad

Reputation: 27183

You haven't set up an IS_A relationship between the parent and child classes.

You can do this with the base pragma as Ivan suggests, or you can manipulate the @ISA array. Or you can use the parent pragma.

@ISA:

package SubClass;
our @ISA = qw( BaseClass );

parent:

package SubClass;
use parent qw( BaseClass );

By the way, don't use the indirect object syntax ever. To call your constructor do:

my $foo = SubClass->new();

Also, it looks like you aren't using the strict and warnings pragmas. Do so. Always.

Finally, if you have multiple packages in one file, it is helpful to enclose each package in a block.

Check out perlboot and perltoot, they are handy OOP tutorials in the perldoc.

Update:

I just noticed that your method calls are broken. You need to find the invoking class or instance in each method.

package BaseClass;

sub new { bless {}, shift; }  # horrible constructor - do not reuse.

sub abstract { die "The present situation is abstract"; }

sub method { my $self = shift; $self->abstract; }


package SubClass;

our @ISA = qw( BaseClass );

sub abstract { print "It's alive\n" );

In the script:

my $obj = SubClass->new;
$obj->method;

my $base = BaseClass->new;
$base->method;

Definitely read the tutorials I linked to. They will help you.

Upvotes: 6

Eric Strom
Eric Strom

Reputation: 40142

There are some problems with your code, you need to tell the subclass what its parent class is. You also probably need to setup your constructors to pass through to the parent class. There were also a few misspellings in there.

package BaseClass;

sub new {
    bless {} => shift;
}
sub method1 {
    my $self = shift;

    return $self->someAbstractMethod();
}


sub someAbstractMethod
{
     die "oops, this is an abstract method that should " . 
         "be implemented in a subclass";
}


package SubClass;
use base 'BaseClass';

sub new {
    shift->SUPER::new
}

sub someAbstractMethod
{
     print "now we implement the asbtract method\n";
}


package main;

my $obj = BaseClass->new;

eval {$obj->method1(); 1} or warn $@;

my $subobj = SubClass->new;

$subobj->method1();

Upvotes: 3

Related Questions