Ошибка метода не найдена при наследовании абстрактного метода в ООП Perl - PullRequest
1 голос
/ 08 апреля 2010

У меня есть подкласс, который вызывает метод из суперкласса. Метод в суперклассе использует метод, который определен в суперклассе как абстрактный (не совсем абстрактный), но реализован в подклассе.

Например:

package BaseClass;

sub new
{

}
sub method1 {

    return someAbstractMethod();
}



sub someAbtsractMethod
{
     die "oops, this is an abstract method that should " . 
         "be implemented in a subclass" ;
}
1;

package SubClass;

sub new
{

}

sub someAbtsractMethod
{
     print "now we implement the asbtract method";
}
1;

Теперь, когда я делаю:

$sub = new SubClass();
$sub->method1();

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

Ответы [ 4 ]

5 голосов
/ 08 апреля 2010

Вы не установили отношения IS_A между родительским и дочерним классами.

Вы можете сделать это с прагмой base, как предлагает Иван, или вы можете манипулировать массивом @ISA. Или вы можете использовать parent прагму.

@ ISA:

package SubClass;
our @ISA = qw( BaseClass );

parent

package SubClass;
use parent qw( BaseClass );

Кстати, никогда не используйте косвенный синтаксис объекта. Для вызова вашего конструктора выполните:

my $ foo = SubClass-> new ();

Кроме того, похоже, что вы не используете строгие и предупреждения прагмы. Сделай так. Всегда.

Наконец, если у вас есть несколько пакетов в одном файле, полезно заключить каждый пакет в блок.

Ознакомьтесь с perlboot и perltoot , это удобные руководства по ООП в perldoc.

Обновление:

Я только что заметил, что ваши вызовы методов прерываются. Вам нужно найти вызывающий класс или экземпляр в каждом методе.

package BaseClass;

sub new { bless {}, shift; }  # horrible constructor - do not reuse.

sub abstract { die "The present situation is abstract"; }

sub method { my $self = shift; $self->abstract; }


package SubClass;

our @ISA = qw( BaseClass );

sub abstract { print "It's alive\n" );

В сценарии:

my $obj = SubClass->new;
$obj->method;

my $base = BaseClass->new;
$base->method;

Обязательно прочитайте учебники, на которые я ссылался. Они вам помогут.

3 голосов
/ 08 апреля 2010

Ваша основная проблема в том, что вы вообще не используете вызовы методов. Если бы вы сделали

sub method1 {
  my $self = shift;
  $self->someAbstractMethod();
}

в базовом классе (и при условии правильной настройки наследования) все будет работать. Но когда вы пишете someAbstractMethod(), это не вызов метода, это вызов функции, поэтому он разрешается сразу во время компиляции, без учета полиморфизма (типа объекта).

2 голосов
/ 08 апреля 2010

Если вы только начинаете с Perl OO, не забудьте проверить Moose . См. Также Moose :: Manual :: Unsweeteed для сравнения Moose с обычным стилем Perl 5 OOP.

2 голосов
/ 08 апреля 2010

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

package BaseClass;

sub new {
    bless {} => shift;
}
sub method1 {
    my $self = shift;

    return $self->someAbstractMethod();
}


sub someAbstractMethod
{
     die "oops, this is an abstract method that should " . 
         "be implemented in a subclass";
}


package SubClass;
use base 'BaseClass';

sub new {
    shift->SUPER::new
}

sub someAbstractMethod
{
     print "now we implement the asbtract method\n";
}


package main;

my $obj = BaseClass->new;

eval {$obj->method1(); 1} or warn $@;

my $subobj = SubClass->new;

$subobj->method1();
...