Reputation: 40499
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?
Upvotes: 2
Views: 172
Reputation: 118118
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.
Upvotes: 5
Reputation: 385655
However, this construct doesn't seem to work if
Parent
does not explicitely define a new function (butGrandparent
does).
Not true.
$ perl -E'
package Grandparent {
sub new { CORE::say(__PACKAGE__) }
}
package Parent {
our @ISA = "Grandparent";
}
package Child {
our @ISA = "Parent";
sub new { my $class = shift; $class->SUPER::new(); }
}
Child->new();
'
Grandparent
Can't locate package Net::FTP::File
This a warning obtained when you try to inherit from a class that hasn't been declared. Specifically, you are trying to use Net::FTP::File without having loaded it.
Replace
our @ISA = 'Net::FTP::File';
with
use Net::FTP::File qw( );
our @ISA = 'Net::FTP::File';
or with
use parent 'Net::FTP::File';
Can't locate object method "new" via package "tq84_ftp"
This message is a bit unclear, but it's due to the fact that Net::FTP::File->new
doesn't exist. Net::FTP::File isn't a class, much less a subclass of Net::FTP. It has no methods, much less a new
method. It makes no sense to inherit from Net::FTP::File.
You appear to want to create a Net::FTP object, so replace
use parent 'Net::FTP::File';
with
use parent 'Net::FTP';
Finally, you want to load Net::FTP::File for the methods it adds to Net::FTP objects (which includes object of classes that inherit from Net::FTP). To do that, simply add
use Net::FTP::File qw( );
Upvotes: 6