Alan Moore
Alan Moore

Reputation: 6575

Perl: How to make sure overridden method is called when accessed from within the base class

I have a base class which calls a method which is overridden in a child class, in Perl. Currently, it still calls the base class version of the method, but I want it to call the base if there is one. Here is a simplified rendition of my code:

package Test;

use strict;
use warnings;

sub Main
{
    my $self = shift;
    return $self->SomeFunc();
}

sub SomeFunc
{
    my $self = shift;
    #...
    return 1;
}

package Test2;

use strict;
use warnings;

use base qw(Test);

sub SomeFunc
{
    my $self = shift;
    #...
    return 0;
}

package main;
use Test2;

my $test = new Test2();
print $test->Main();

and I am getting a 1 when I run this!

PS my apologies, I'm not used to creating examples in working perl code, please forgive the obvious errors.

Upvotes: 2

Views: 329

Answers (2)

Borodin
Borodin

Reputation: 126722

The problem would be in your constructor, but you don't have one so your code doesn't even do what you say it does

You have probably written something like

sub new {
    bless {};
}

which blesses an empty hash into the current package. Instead you need to take the class name from the first parameter passed to the constructor, like this

You should also avoid using capital letters in your lexical identifiers as they are reserved for global identifiers like package names. If you must use CamelCase then at least makeSureTheFirstLetterIsLowerCase. The standard for both Perl and Python is to use the much_clearer_snake_case

Test.pm

package Test;

use strict;
use warnings;

sub new {
    my $class = shift;
    bless {}, $class;
}

sub main {
    my $self = shift;
    $self->some_func();
}

sub some_func {
    my $self = shift;
    'Test::some_func';
}

Test2.pm

package Test2;

use strict;
use warnings;

use parent 'Test';

sub some_func {
    my $self = shift;
    'Test2::some_func';
}

main.pl

use strict;
use warnings;

my $test = Test->new;
print $test->main, "\n";

$test = Test2->new;
print $test->main, "\n";

output

Test::some_func
Test2::some_func

Upvotes: 3

dkatzel
dkatzel

Reputation: 31648

new doesn't mean anything in perl unless you make a function with that method name.

You need to bless an object

You can either directly bless an object

my $test = { };
bless $test, "Test2";

or make a new method that does the blessing for you:

sub new{
    my $class = shift;
    my $test = { };
    bless $test, $class;
}

Upvotes: 1

Related Questions