如何在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。
答案 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
差异是......
所以这个例子只涵盖了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.