2008-11-03 51 views
14

如何在Perl中应用'use base'来从一些基本模块继承subs?如何在Perl中使用'use base'继承子例程?

我习惯于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。

回答

20

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; 
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”))。

+0

不,它不会像这样结束 - 它将查找继承层次结构,因此可能会调用完全不同的包中的子。另外,你的例子不是有效的语法。 (我知道你在说什么,但是你怎么说这样做肯定会让人更加困惑,因为OP更令人困惑。) – 2008-11-03 11:57:58

+0

当然,它走的是继承树。毕竟,问题是关于继承。请注意,OP用于使用C++继承,所以我认为这很明显。 – tsee 2008-11-03 12:51:11

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"; 
} 
5

一点题外话,很少有很好的理由use base,而不是较新的use parent

+0

有趣。但是有没有什么好的理由使用父母? – innaM 2008-11-03 14:53:48

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 

的差异....

  • 构造自动由定义你&
  • 继承创建 “扩展”命令而不是“使用基地”。

所以本实施例中仅覆盖麋冰山;-)

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.