8

#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";

I am getting the error Can't locate object method "add" via package "child1" at ./test.pl line 8. I want to access the base class add method and I am getting this above error

please clarify..

4

3 回答 3

10

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

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

  1. use parent 'cal'不要操纵@ISA自己。
  2. 面向对象的模块几乎没有理由使用Exporter.
  3. child1 可以不用reblessingnew来编写,因为 parentnew是继承的。继承new的以已经支持继承的方式编写。
  4. 不要给你的模块小写的名字,这些是为“pragmas”保留的。该parent模块已经存在,我在第一点使用了它。
于 2013-07-24T12:06:59.663 回答
7

@ISA必须是公共包变量,而不是私有词法 ( my)。对@EXPORT. 更改所有这些声明myour

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

关于样式,如果您使包含模块代码的文件的路径与它们的包名称匹配,您将避免相当大的混乱。您最好注意perlmod 文档中描述的完善的约定。

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

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

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

卡尔.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;

孩子1.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;

测试.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";

输出:

这是来自儿童班
3=总和1
这是来自父类
3=总和2
这是来自父类
3=总和3
于 2013-07-24T12:05:23.777 回答
6

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

并且 .pl 模块不应该有 @ISA 或在包中找到的其他“我们的”声明,也不应该有任何与导出器相关的东西。

如前所述,将包装内容的“我的”更改为“我们的”。“我的”向外界隐藏事物,就好像这些陈述从未存在过一样。

在“cal”类中,您想要以下内容吗?我喜欢 SUPER,因为它确实显示了正在发生的事情并且更加通用

包子1;
使用出口商;
我们的@ISA=qw(cal 出口商);

子新{
        我的 $class=shift;
        我的 $ref= $class->SUPER::new() ;
        返回 $ref;
        }
}

最后一点:您可能需要在最后的打印语句上添加一个“\n”。如果没有它,缓冲区在某些环境中可能无法在退出时正确刷新,因此您将永远看不到输出。

于 2013-07-24T12:47:13.013 回答