Как вызвать метод в базовом классе в Perl

#ребенок.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); 
        }

##родитель.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";

Я получаю ошибку, не могу найти метод объекта "добавить" через пакет "child1" at ./test.pl строка 8. Я хочу получить доступ к методу add базового класса и я получаю это выше ошибки

просьба уточнить..

3 ответов


The .модули pm не нужны и, скорее всего, не хотят,#!/usr/bin / perl lines. Это только для программ, предназначенных для выполнения из командной строки, как ваш .модуль pl. В то время как вы можете "perl-cw" ваш .модули pm или другая отладка командной строки с ними, это не обычное" производственное " использование.

и .модули pl не должны иметь @ISA или другие" наши " декларации, найденные в пакетах, или любые связанные с экспортером вещи.

Как уже было сказано, измените " my " на упакуйте вещи в "наши". "Мое" скрывает вещи для посторонних, как будто заявлений никогда не было.

в классе " cal " вы хотите что-то вроде следующего? Я предпочитаю супер, как это действительно показывает, что происходит и гораздо более общие.

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

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

один заключительный момент: вам может понадобиться "\n" в окончательном операторе печати. Без него буфер может не сбросить правильно при выходе в некоторых средах, поэтому вы никогда не увидите вывод.


главным виновником здесь является my @ISA. Чтобы наследование работало, вы должны использовать пакет @ISA (объявим его с our).

однако в вашем коде есть некоторые проблемы помимо этого:

  1. пожалуйста use parent 'cal' вместо манипулирования @ISA себя.
  2. объектно-ориентированные модули имеют мало оснований для использования Exporter.
  3. пакета child1 это new может быть написана без reblessing, потому что родителей new передается по наследству. Унаследованное new написано таким образом, что уже поддерживает наследование.
  4. не давайте своим модулям строчные имена, они зарезервированы для"прагм". The parent модуль уже существует, и я использовал его в моем 1-ом пункте.

@ISA должна быть переменная открытого пакета, а не частная лексическая (my). Же для @EXPORT. Изменить my to our на все эти заявления.

еще лучше, в зависимости от версии perl у вас есть, упростить вам жизнь с parent или base pragma для загрузки суперклассов и настройки отношений классов.

что касается стиля, вы избежите значительной путаницы, если сделаете пути к файлам, содержащим код ваших модулей, соответствуют их именам пакетов. Вам следует прислушаться к устоявшемуся соглашению, описанному в документация perlmod.

имена модулей также капитализируются, если они не функционируют как прагмы; прагмы фактически являются директивами компилятора и иногда называются " прагматическими модулями "(или даже" прагматами", если вы классик).

модуль Cal использует внутреннее _initialize метод, как описано в perlobj документация для облегчения наследования конструктора.

см. ниже полный рабочий пример.

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, так.ПМ

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