我如何调用 grandparent 的构造函数(因为 parent 的构造函数未定义)?

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

我相信,在 Perl 中调用 parent 的 class' 构造函数的规范方法是:

package Child;
our @ISA = 'Parent';

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

但是,如果 Parent 没有明确定义 new 函数(但 Grandparent 定义了),则此构造似乎不起作用。

例如 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();

输出:

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.

如何指定我希望 Perl 找到正确的(此处:grantparent 的)new 函数?

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

不正确。

$ 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

这是当您尝试从尚未声明的 class 继承时获得的警告。具体来说,您试图在未加载的情况下使用 Net::FTP::File。

替换

our @ISA = 'Net::FTP::File';

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

或与

use parent 'Net::FTP::File';

Can't locate object method "new" via package "tq84_ftp"

这条消息有点不清楚,但这是因为 Net::FTP::File->new 不存在。 Net::FTP::File 不是 class,更不是 Net::FTP 的子 class。它没有方法,更不用说 new 方法了。从 Net::FTP::File.

继承是没有意义的

您似乎想要创建一个 Net::FTP 对象,因此替换

use parent 'Net::FTP::File';

use parent 'Net::FTP';

最后,您要为它添加到 Net::FTP 对象(包括继承自 Net::FTP 的 class 对象)的方法加载 Net::FTP::File。为此,只需添加

use Net::FTP::File qw( );

您似乎假设 Net::FTP::FileNet::FTP 的子class,因此

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

应该调用 Net::FTPnew 方法。

然而,事实上,Net::FTP::File并没有继承自Net::FTP。相反,它重新定义了 Net::FTP 中的一些方法。因此,如果您的 class 继承自 Net::FTP::File,它将不是 Net::FTP.

的子代

如果您查看 source code for Net::FTP,您可以很容易地看到这一点。注意下面没有use base 'Net::FTP'use parent 'Net::FTP'our @ISA = qw( Net::FTP )

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;
}

等等等等