如何在Perl中调用基类中的方法

时间:2013-07-24 11:57:20

标签: perl

#child.pm

#!/usr/bin/perl
package child1;
use strict;
use warnings;
use Exporter;
use parent;
my @ISA=qw(cal Exporter);
sub new{
        my $class=shift;
        my $ref=cal->new();
        bless ($ref,$class);
        return $ref;
        }
sub add{
        my $ref=shift;
        print "This is from child class";
        my($a,$b)=@_;
        return ($a+$b); 
        }

#的#parent.pm

#!/usr/bin/perl
package cal;
use strict;
use warnings;
use Exporter;
my @EXPORT=qw(add);
my @ISA=qw(Exporter EXPORT);
sub new{
        my $class=shift;
        my $ref=[];
        bless ($ref,$class);
        return $ref;
        }

sub add{
        my $ref=shift;
        my $a=shift;
        my $b=shift;
        return ($a+$b);
        }
1;

#test.pl

#!/usr/bin/perl
use strict;
use warnings;
use Exporter;
use child;
my @ISA=qw(child1 Exporter);
my $obj=new child1();
my $sum=$obj->add(1,2);
print "$sum=sum";

我收到错误无法在./test.pl第8行通过包“child1”找到对象方法“add”。 我想访问基类add方法 我收到上述错误

请澄清..

3 个答案:

答案 0 :(得分:10)

这里的主要罪魁祸首是my @ISA。要继承工作,您必须使用包@ISA(使用our声明它)。

但是,除此之外,您的代码中存在一些问题:

  1. use parent 'cal'而不是自己操纵@ISA
  2. 面向对象的模块没有理由使用Exporter
  3. 可以在不重复的情况下编写child1的new,因为父级的new是继承的。继承的new是以一种已经支持继承的方式编写的。
  4. 不要给你的模块小写名称,这些是为“pragma”保留的。 parent模块已经存在,我在第一点使用它。

答案 1 :(得分:6)

.pm模块不需要,也可能不需要#!/ usr / bin / perl行。这仅适用于要从命令行执行的程序,例如.pl模块。虽然你可以'perl -cw'你的.pm模块,或者用它们进行其他命令行调试,但这不是正常的“生产”使用。

.pl模块不应该包含@ISA或其他“我们的”声明,也不应该包含任何与导出器相关的内容。

如前所述,将“my”的包装内容改为“我们的”。 “我的”向外人隐瞒事情,好像这些陈述从未出现过。

在“cal”课程中,您想要以下内容吗?我赞成SUPER,因为它真实地展示了上发生的事情,并且更加通用

package child1;
use Exporter;
our @ISA=qw(cal Exporter);

sub new{
        my $class=shift;
        my $ref=$class->SUPER::new();
        return $ref;
        }
}

最后一点:您可能需要在最终的打印声明中使用“\ n”。没有它,缓冲区在某些环境中可能无法在退出时正确刷新,因此您永远不会看到输出。

答案 2 :(得分:4)

@ISA必须是公共包变量,而不是私有词法(my)。 @EXPORT也是如此。在所有这些声明中将my更改为our

更好的是,根据您拥有的perl版本,使用parentbase pragma简化您的生活,以加载超类并设置类关系。

关于样式,如果使包含模块代码的文件的路径与其包名匹配,则可以避免相当大的混淆。你应该注意perlmod documentation中描述的完善的惯例。

  

模块名称也大写,除非它们作为编译指示运行; pragma实际上是编译器指令,有时被称为“实用模块”(如果你是古典主义者,甚至称为“pragmata”)。

Cal模块使用perlobj documentation中描述的内部_initialize方法来促进构造函数的继承。

请参阅下面的完整工作示例。

Cal.pm

package Cal;

use strict;
use warnings;

sub new {
  my $class=shift;
  my $self=[];
  bless ($self,$class);
  $self->_initialize();
  return $self;
}

sub _initialize {}

sub add {
  my $ref=shift;
  my $a=shift;
  my $b=shift;
  print "This is from parent class\n";
  return ($a+$b);
}

1;

Child1.pm

package Child1;

use warnings;
use strict;

use v5.10.1;  # when parent was added to the core
use parent "Cal";

# if you have an older perl, use base instead of parent
# use base "Cal";

sub _initialize {
  my $self=shift;
  push @$self, "I am a " . ref($self) . "!";
}

sub add{
  my $self=shift;
  my($a,$b)=@_;
  print "This is from child class\n";
  return ($a+$b);
}

1;

test.pl

#!/usr/bin/perl

use strict;
use warnings;

use Child1;

my $obj=Child1->new();

my $sum1=$obj->add(1,2);
print "$sum1=sum1\n";

# call the add method in Cal
my $sum2=$obj->Cal::add(1,2);
print "$sum2=sum2\n";

# call add as a class method of Cal, which
# happens to work in this case because Cal::add
# does not use the instance passed to it
my $sum3=Cal->add(1,2);
print "$sum3=sum3\n";

输出:

This is from child class
3=sum1
This is from parent class
3=sum2
This is from parent class
3=sum3