代码之家  ›  专栏  ›  技术社区  ›  slashmais

如何在Perl中继承带有“use base”的子程序?

  •  16
  • slashmais  · 技术社区  · 16 年前

    如何在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 回复  |  直到 7 年前
        1
  •  23
  •   brian d foy    16 年前

    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;
    
        2
  •  10
  •   AndyG    8 年前

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

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

        3
  •  5
  •   Aristotle Pagaltzis    16 年前

    顺便说一句,没有什么好理由 use base 而不是较新的 use parent .

        4
  •  5
  •   brian d foy    16 年前

    在我看来,你在这里混淆了两件事:面向对象和过程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";
    }
    
        5
  •  4
  •   jinsungy    16 年前

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

        6
  •  1
  •   Axeman maxelost    12 年前

    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.