2

我不知道这是否可能,但我想从 Perl 调用一个已知的子类函数。我需要一些“通用”的东西来称呼更具体的东西。我的超类将假定它的子类的所有类都定义了一个已知函数。我想这类似于Java“实现”。

例如,假设我有以下代码:

GenericStory.pm

package Story::GenericStory;

sub new{
   my $class = shift;
   my $self = {};

   bless $self, class;
   return $self;
}

sub tellStory {
   my $self;

   #do common things
   print "Once upon a time ". $self->specifics();
}

#

Story1.pm

package Story::Story1;
use base qw ( Story::GenericStory );

sub new {
   my $class = shift;
   my $self = $class->SUPER::new(@_);

   return $self;
}

sub specifics {
   my $self;
   print " there was a dragon\n";
}

#

Story2.pm

package Story::Story2;
use base qw ( Story::GenericStory );

sub new {
   my $class = shift;
   my $self = $class->SUPER::new(@_);

   return $self;
}

sub specifics {
   print " there was a house\n";
}

#

MAIN

my $story1 = Story::Story1->new();
my $story2 = Story::Story2->new();

#Once upon a time there was a dragon.
$story1->tellStory();


#Once upon a time there was a house.
$story2->tellStory();

编辑:

代码工作正常。我只是忘记了“我的 $self = shift;” 在tellStory()中;

4

2 回答 2

5

您的代码可以正常工作(模数微不足道的错误);您可能想在超类中添加:

sub specifics {
    require Carp;
    Carp::confess("subclass does not implement required interface");
}

或类似的。

于 2013-06-26T18:27:25.517 回答
0

你想要的很像一个特征(或者在 Perl 中:一个角色)。

特征是面向对象系统的一个相对较新的补充。它们就像接口,因为它们可以需要一个继承类来实现某些方法,但它们就像一个抽象超类,因为它们可以自己提供某些方法。

Moose 对象系统允许角色。一个类可以声明with一个特定的角色。这里你的例子写成MooseX::Declare

use MooseX::Declare;

role Story::StoryTeller{
    requires 'specifics';

    method tellStory() {
        print "Once upon a time ";
        $self->specifics();
    }
}

class Story::Story1 with Story::StoryTeller {
    method specifics() {
        print " there was a dragon\n";
    }
}

class Story::Story2 with Story::StoryTeller {
    method specifics() {
        print " there was a house\n";
    }
}

my $story1 = Story::Story1->new();
my $story2 = Story::Story2->new();

#Once upon a time there was a dragon.
$story1->tellStory();
#Once upon a time there was a house.
$story2->tellStory();

这不是继承:$story1->isa("Story::StoryTeller")是假的,但它起到了这个作用:$story1->DOES("Story::StoryTeller")是真的。

对于每一个类都表示DOES某个角色,该类的一个实例的can所有方法的角色。因此,$story1->can("tellStory")是正确的,并且在每个Story::StoryTeller实例中相反,$instance->can("specifics")将是正确的。

角色不能单独实例化。

于 2013-06-26T19:15:18.973 回答