Search code examples
perlperl-modulemoose

Perl - With overriden method avoid super() is called


I'm trying to create the abstract method pattern using Perl and Moose. What I don't understand is that if I override a method from the AbstractClass it will eventually be called anyway. Why is this and is there a way to avoid the superclass from being called?

Main

package main;
use AbstractSort;
use OrderedSort;

# Sub class test
my $ordered = OrderedSort->new(array => [1, -1, 23, 34123, -24324]);
$ordered->sortData();

AbstractClass

package AbstractSort;
use namespace::autoclean; # Trims EXPORTER 
use Moose;

has 'array' => (traits  => ['Array'],
            is => 'ro', 
            isa => 'ArrayRef[Int]', 
            default => sub { [] },
            handles => {    
                get_array => 'get',
                count_array  => 'count',
            });

sub sortData{
    my $self = shift;

    print "Sorting data..\n";

    _sortAlgorithm($self->array);

    # ...
}

# Protected method here is the actual algorithm
sub _sortAlgorithm {
    die 'You must override _sortAlgorithm() in a subclass';
    # but Moose will always call the superclass which then makes it die
} 

SubClass

package OrderedSort;
use namespace::autoclean; # Trims EXPORTER 
use Moose;
extends 'AbstractSort';

# Override and mmpl _sortAlgorithm
override _sortAlgorithm => sub {
   my $self = shift;
   # ....
};

before '_sortAlgorithm' => sub {
    my $self = shift;
    # ...

    return;
};

Solution

  • You are calling _sortAlgorithm as a function in the same package in AbstractSort`, and not as a method.

    sub sortData {
        my $self = shift;
    
        # there is something missing here!
        _sortAlgorithm( $self->array );
    }
    

    That way, it will always be called in the same package, because it's not an OOP method call.

    You need to do $self->_sortAlgorithm instead.

    sub sortData {
        my $self = shift;
    
        print "Sorting data..\n";
    
        $self->_sortAlgorithm( $self->array );
    
        # ...
    }
    

    It will now not die any more, because it looks up the _sortAlgorithm method on $self, which is an instance of your subclass.

    The fact that you actually have my $self = shift on your overridden method could have given that away, as you were also not passing $self into it.


    You should also not be passing around $self->array. The algorithm method also has access to $self->array, so if you want to sort the data that is attached to your object, just use it directly in there.

    Also note that typical naming conventions in Perl suggest snake_case method and variable names, and CamelCase package names.