Reputation: 403
I don't know if this is possible, but I would like to call a known subclass function from Perl. I need something "generic" to call something more specific. My superclass is going to assume that all classes that subclass it have a known function defined. I guess this is similar to Java "implements".
For example let's say I have the following code:
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();
EDIT:
The code works fine. I simply forgot a "my $self = shift;" in tellStory();
Upvotes: 2
Views: 300
Reputation: 57600
What you want is very much like a trait (or in Perl: a role).
Traits are a relatively recent addition to object oriented systems. They are like interfaces in that they can require an inheriting class to implement certain methods, but they are like a abstract superclass in that they can provide certain methods themselves.
The Moose object system allows roles. A class can be declared with
a certain role. Here your example written 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();
This isn't inheritance: $story1->isa("Story::StoryTeller")
is false, but it does this role: $story1->DOES("Story::StoryTeller")
is true.
For every class that DOES
a certain role, an instance of that class can
all methods of the role. Therefore, $story1->can("tellStory")
is true, and in reverse for every Story::StoryTeller
instance, $instance->can("specifics")
will be true.
A role cannot be instantiated on its own.
Upvotes: 0
Reputation: 98398
Your code works fine as is (modulo trivial errors); you may want to add in the superclass:
sub specifics {
require Carp;
Carp::confess("subclass does not implement required interface");
}
or similar.
Upvotes: 5