15

如何在 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。

4

6 回答 6

23

C++ 机制与 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;
于 2008-11-03T10:50:45.933 回答
10

你应该看看使用Moose,它是 Perl5 的后现代对象系统。您可能会发现它比使用标准 Perl OO 语义更容易掌握……尤其是来自另一种 OO 语言时。

这是您问题的驼鹿版本....

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 冰山一角 ;-)

于 2008-11-03T17:10:48.567 回答
5

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

您的 TestBase.pm 模块似乎希望作为 Perl 对象(Perl oo 风格)运行,但您的 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 面向对象

#! /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";
}
于 2008-11-03T10:55:57.373 回答
5

作为旁注,没有什么好的理由use base而不是较新的.use parent

于 2008-11-03T12:01:26.303 回答
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->method("foo")。)

于 2008-11-03T10:46:00.967 回答
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.
于 2008-11-03T21:17:40.083 回答