Как мне наследовать подпрограммы в Perl с помощью «use base»? - PullRequest
14 голосов
/ 03 ноября 2008

Как применить «использование базы» в Perl для наследования подпрограмм от некоторого базового модуля?

Я привык к механизму наследования C ++, и все сайты, которые я гуглил для этого, вызывали больше путаницы, чем помощи. Я хочу сделать что-то вроде следующего:

#! /usr/bin/perl
#The base class to inherit from
use strict;
use warnings;

package 'TestBase';

#-------------------------------
sub tbSub
{
    my ($self, $parm) = @_;
    print "\nTestBase: $parm\n";
}

1;

.

#! /usr/bin/perl
#The descendent class
use strict;
use warnings;

use base qw(TestBase);
sub main;
sub mySub;

#-------------------------------
#Entry point...
main();

#---code------------------------
sub main
{
    mySub(1);
    tbSub(2);
    mySub(3);
}

#-------------------------------
sub mySub
{
    my $parm = shift;
    print "\nTester: $parm\n";
}

Perl жалуется / не может найти tbSub.

Ответы [ 6 ]

21 голосов
/ 03 ноября 2008

Механика C ++ не сильно отличается от механики Perl: чтобы использовать наследование, вам нужны два класса: базовый класс и класс наследования. Но у вас нет потомков класса.

Вам также не хватает конструктора. В отличие от C ++, Perl не предоставит вам конструктор по умолчанию.

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

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

То, что вы действительно хотите, выглядело бы примерно так:

my $foo = TestDescendent->new();
$foo->main();


package TestBase;

sub new {
   my $class = shift;
   return bless {}, $class;
}

sub tbSub
{
   my ($self, $parm) = @_;
   print "\nTestBase: $parm\n";
}

package TestDescendent;
use base 'TestBase';

sub main {
    my $self = shift;
    $self->mySub( 1 );
    $self->tbSub( 2 );
    $self->mySub( 3 );
}

sub mySub
{
    my $self = shift;
    my $parm = shift;
    print "\nTester: $parm\n";
}

1;
10 голосов
/ 03 ноября 2008

Вы должны взглянуть на использование Moose , которое является постмодернистской объектной системой для Perl5. Вероятно, вам будет гораздо проще понять, чем использовать стандартную семантику Perl OO ... особенно, если вы используете другой язык OO.

Вот Moose версия вашего вопроса ....

package TestBase;
use Moose;

sub tbSub {
   my ($self, $parm) = @_;
   print "\nTestBase: $parm\n";
}


package TestDescendent;
use Moose;
extends 'TestBase';

sub main {
    my $self = shift;
    $self->mySub( 1 );
    $self->tbSub( 2 );
    $self->mySub( 3 );
}

sub mySub {
    my ($self, $parm) = @_;
    print "\nTester: $parm\n";
}


package main;
my $foo = TestDescendent->new();
$foo->main

Различия ...

  • Конструктор автоматически создан для вас &
  • Наследование, определенное командой "extends" вместо "use base".

Так что этот пример покрывает только верхушку айсберга Лося; -)

5 голосов
/ 03 ноября 2008

Как примечание, у use base нет более веской причины, чем у новой use <a href="http://p3rl.org/parent" rel="noreferrer">parent</a>.

5 голосов
/ 03 ноября 2008

Мне кажется, вы смешиваете две вещи: объектно-ориентированный и процедурный Perl. Perl OO является своего рода «другим» (как в не массовом, но работоспособном).

Кажется, ваш модуль TestBase.pm будет работать как объект Perl (стиль Perl oo), но ваш скрипт Perl хочет получить к нему доступ как к «обычному» модулю. Perl работает не так, как C ++ (как вы поняли), поэтому вам придется конструировать код по-другому. См. Книги Дамиана Конвея для объяснений (и более умного кода, чем мой ниже).


Процедурный:

#! /usr/bin/perl
#The module to inherit from

package TestBase;
  use strict;
  use warnings;

  use Exporter ();
  our @ISA         = qw (Exporter);
  our @EXPORT      = qw (tbSub);

#-------------------------------
sub tbSub
{
    my ($parm) = @_;
    print "\nTestBase: $parm\n";
}

1;

.

#! /usr/bin/perl
#The descendent class
use strict;
use warnings;

use TestBase; 
sub main;
sub mySub;

#-------------------------------
#Entry point...
main();

#---code------------------------
sub main
{

    mySub(1);
    tbSub(2);
    mySub(3);
}

#-------------------------------
sub mySub
{
    my $parm = shift;
    print "\nTester: $parm\n";
}

Perl OO

#! /usr/bin/perl
#The base class to inherit from

package TestBase;
  use strict;
  use warnings;

#-------------------------------
sub new { my $s={ };
    return bless $s;
}
sub tbSub
{
    my ($self,$parm) = @_;
    print "\nTestBase: $parm\n";
}

1;

.

#! /usr/bin/perl
#The descendent class
use strict;
use warnings;

use TestBase; 
sub main;
sub mySub;

#-------------------------------
#Entry point...
main();

#---code------------------------
sub main
{
    my $tb = TestBase->new();
    mySub(1);
    $tb->tbSub(2);
    mySub(3);
}

#-------------------------------
sub mySub
{
    my $parm = shift;
    print "\nTester: $parm\n";
}
4 голосов
/ 03 ноября 2008

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

main->tbSub(2);

Однако, что вы действительно хотите, это наследовать метод в правильный класс:

package Derived;
use base "TestBase";

package main;
Derived->somemethod("foo");

Вызов методов в текущем пакете как функции не будет передаваться ни в $ self, ни в объект "this", ни в имя класса магическим образом Внутренне

Class->somemethod("foo")

по сути заканчивается тем, что его называют

Class::somemethod("Class", "foo")

внутри. Конечно, это предполагает, что в Class есть подпрограмма / метод с именем "somemethod". Если нет, то будут проверены суперклассы Class, и если у них также нет метода "somemethod", вы получите фатальную ошибку. (Та же логика применяется для метода $ obj-> ("foo").)

1 голос
/ 04 ноября 2008
Синтаксис

OO использует оператор -> для отделения сообщения и аргументов от получателя сообщения. Краткая иллюстрация ниже.

You->do_something( @params );

OR 

$you->do_something( @params );

package A;

sub do_neat_thing { 
    my ( $class_or_instance, @args ) = @_;
    my $class = ref( $class_or_instance );
    if ( $class ) {
         say "Instance of '$class' does a neat thing.";
    }
    else { 
        say "$class_or_instance does a neat thing.";
    }
}

...
package main;
A->do_neat_thing();      # A does a neat thing.
my $a_obj = A->new();
$a_obj->do_neat_thing();     # Instance of 'A' does a neat thing.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...