http://www.perlmonks.org?node_id=1056542


in reply to Inherit custom sort method from base class

Sort comparison function should be a.. function, not a method.

Thus I don't quite understand how class inheritance applies here.

Would you mind simplifying your code to proof-of-concept example and posting here so we would see the problem?
  • Comment on Re: Inherit custom sort method from base class

Replies are listed 'Best First'.
Re^2: Inherit custom sort method from base class
by adaughterson (Initiate) on Oct 01, 2013 at 22:23 UTC

    I can certainly do that.

    The base-class:
    Package MyBaseClass; sub new { my $class = shift; my $self = {}; bless($self,$class); $self->_init(); return $self; } sub _init { my $self = shift; @{$self->{things}} = qw(thing_0.1 thing_0.2 thing_0.3 thing_11.0 thi +ng_11.1); # etc,etc return $self; } # $a and $b don't seem to exist within this context sub specialSort { my $self = shift; my @aParts = split(/[_.]/, $a); my @bParts = split(/[_.]/, $b); return 1 if (int $a_parts[1] > int $b_parts[1] || ($a_parts[1] eq $b +_parts[1] && (int $a_parts[2]) > (int $b_parts[2]))); return -1 if (int $a_parts[1] < int $b_parts[1] || ($a_parts[1] eq $ +b_parts[1] && (int $a_parts[2]) < (int $b_parts[2]))); return 0 if ($a eq $b); die((caller(0))[3] . " LOGIC error."); } 1;
    The subclass:
    package MySubclass; require MyBaseClass; our @ISA = qw(MyBaseClass); sub new { my $class = shift; my $self = {}; bless($self,$class); $self->_init(); return $self; } sub _init { my $self = shift; MyBaseClass::_init($self); return $self; } sub doSomething { my $self = shift; # this works foreach my $thing(sort specialSort @{$self->{things}}) { # do something with $thing... } # this doesn't work foreach my $thing(sort $self->specialSort @{$self->{things}}) { # do something with $thing... } } sub specialSort { # Notice that there is no 'my $self = shift' here... my @aParts = split(/[_.]/, $a); my @bParts = split(/[_.]/, $b); return 1 if (int $a_parts[1] > int $b_parts[1] || ($a_parts[1] eq $b +_parts[1] && (int $a_parts[2]) > (int $b_parts[2]))); return -1 if (int $a_parts[1] < int $b_parts[1] || ($a_parts[1] eq $ +b_parts[1] && (int $a_parts[2]) < (int $b_parts[2]))); return 0 if ($a eq $b); die((caller(0))[3] . " LOGIC error."); } 1;
      Try
      sort { $self->specialSort($a, $b) } @{$self->{things}})
      and remove specialSort from MySubclass.
      you have to use 1st and 2nd arguments instead of $a and $b in base class' specialSort

      You cannot use $self->specialSort as subroutine name, so you have to use new "subroutine":
      { $self->specialSort($a, $b) }

      Also, technically, you can put
      use base qw/Exporter/; @EXPORT = qw/specialSort/;

      into base class,
      then remove specialSort from MySubclass, and then it will work.
      but it's probably bad style to mix inheritance and exported functions.

      UPD: fixed $a,$b in code

        Here's another, slightly different approach to what vsespb is talking about. (But I still don't understand how
            $self->specialSort(my ($a, $b))
        works!)

        >perl -wMstrict -le "{ package Base; ;; sub new { my $class = shift; return bless({} => $class)->init(@_); } ;; sub init { my $self = shift; @{ $self->{things} } = (qw(a E d Bee Z cee d C zee E eks), @_); return $self; } ;; sub print { my $self = shift; CORE::print qq{@{ $self->{things}} }; } ;; sub nocase_descending { my $class_obj = shift; return lc($_[1]) cmp lc($_[0]); } ;; } ;; ;; { package Derived; use parent -norequire, qw(Base); ;; sub sort { my $self = shift; return CORE::sort { $self->nocase_descending($a, $b) } @{ $self->{things} } ; } ;; } ;; ;; my $d = Derived->new(qw(SS r QQ p PP q RR s)); ;; $d->print; ;; my @sorted = $d->sort; print qq{@sorted}; ;; @sorted = sort @{ $d->{things} }; print qq{@sorted}; ;; print $d; " a E d Bee Z cee d C zee E eks SS r QQ p PP q RR s zee Z SS s RR r QQ q PP p eks E E d d cee C Bee a Bee C E E PP QQ RR SS Z a cee d d eks p q r s zee Derived=HASH(0x1e931f4)

        Update: Moved  print method from  Derived class 'up' into  Base class (just because I can).

        That worked great! Thanks for the assist :)

        sort { $self->specialSort(my ($a,$b)) } @{$self->{things}} # ...my, because use strict is in play