如何使用'use base'继承Perl中的子例程?

时间:2008-11-03 09:58:28

标签: perl inheritance

如何在Perl中应用'use base'来继承某些基本模块的subs?

我已经习惯了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 个答案:

答案 0 :(得分:21)

C ++ mechnics与Perl机制没什么不同:要使用继承,需要两个类:基类和继承类。但是你没有任何后代课。

你也缺少一个构造函数。与C ++不同,Perl不会为您提供默认构造函数。

您的基类包含错误的语法错误,因此我猜您在发布之前没有尝试过该代码。

最后,正如tsee已经观察到的那样,你必须让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;

答案 1 :(得分:10)

你应该看看使用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”定义的继承。

所以这个例子只涵盖了Moose冰山的一角; - )

答案 2 :(得分:5)

在我看来,你在这里混淆了两件事:面向对象和程序Perl。 Perl OO有点“不同”(不是主流但可行)。

您的TestBase.pm模块似乎希望作为Perl对象(Perl oo-style)运行,但您的Perl脚本希望以“普通”模块的形式访问它。 Perl不像C ++那样工作(如你所知),所以你必须以不同的方式构造你的代码。请参阅Damian Conway的书籍以获得解释(以及比我下面更智能的代码)。


<强>程序:

#! /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";
}

答案 3 :(得分:5)

作为旁注,use base没有充分的理由而不是较新的use parent

答案 4 :(得分:4)

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-&gt;方法(“foo”)。)

答案 5 :(得分:1)

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.