René Nyffenegger René Nyffenegger - 4 months ago 7
Perl Question

How do I call the grandparent's constructor (because the parent's constructor is not defined)?

I believe, the canonical way to call the parent's class' constructor in Perl is:

package Child;
our @ISA = 'Parent';

sub new {
my $class = shift;
my @args = @_;
my $self = $class->SUPER::new(@args);
return $self;
}


However, this construct doesn't seem to work if
Parent
does not explicitely define a
new
function (but
Grandparent
does).

This is the case, for example, with
Net::FTP::File
.

tq84_ftp.pm
:

package tq84_ftp;

use warnings;
use strict;

our @ISA = qw(Net::FTP::File);

sub new {
my $class = shift;
my $self = $class->SUPER::new('localhost')
or die($@);
return $self;
}

1;


script.pl
:

use tq84_ftp;
tq84_ftp->new();


Output:

Can't locate package Net::FTP::File for @tq84_ftp::ISA at tq84_ftp.pm line 10.
Can't locate package Net::FTP::File for @tq84_ftp::ISA at tq84_ftp.pm line 10.
Can't locate object method "new" via package "tq84_ftp" at tq84_ftp.pm line 10.


How do I specify that I want Perl to find the correct (here: grantparent's)
new
function?

Answer

It seems you assume that Net::FTP::File is a subclass of Net::FTP and, therefore

my $self = $class->SUPER::new('localhost') ...

should invoke Net::FTP's new method.

However, in fact, Net::FTP::File does not inherit from Net::FTP. Instead, it redefines some methods in Net::FTP. Therefore, if your class inherits from Net::FTP::File, it will not be child of Net::FTP.

You can see this easily if you look at the source code for Net::FTP. Note that there is no use base 'Net::FTP' or use parent 'Net::FTP' or our @ISA = qw( Net::FTP ) below:

package Net::FTP::File;

use strict;
use warnings;
use Net::FTP;

# ...

sub Net::FTP::pretty_dir {
    shift;
    my $newp = shift;
    if ( defined $newp ) {
        $pretty = $newp;
        $DirProcHash{cols} = $cols{pretty}  if $pretty;
        $DirProcHash{cols} = $cols{utility} if !$pretty;
    }
    return $pretty;
}

# ...

sub Net::FTP::isfile {
    my $ftp = shift;
    return 1 if $ftp->exists(@_) && !$ftp->isdir(@_);
    0;
}

etc etc.

Comments