Perl:使用基础和子类的通用构造函数

时间:2013-10-11 17:46:00

标签: perl class constructor shared

我试图初始化基类和子类而不必复制构造函数。这就是我得到的:

tstbase.pm:

package tstbase;
use Exporter qw(import);
our @EXPORT = qw(&new);
my %config = (
    "class" => "tstbase",
);

sub new {
    my $class = shift;
    my $self;
    $self->{"name"} = $config{"class"};
    bless ($self, $class);
    return $self;
};
1;

tstsubclass.pm:

package tstsubclass;
use tstbase;
my %config = (
  "class" => "tstsubclass",
);
1;

tst.pl:

#!/usr/bin/perl
use tstsubclass;

my $baseobj = tstbase->new;
print "Testbase ".$baseobj->{"name"}."\n";
my $subobj = tstsubclass->new;
print "Testsubclass ".$subobj->{"name"}."\n";

tst.pl的出局是

Testbase tstbase
Testsubclass tstbase

但我正在寻找

Testbase tstbase
Testsubclass tstsubclass
当我将“sub new {..}”例程复制到tstsubclass.pm时,我得到了

。有没有办法避免这种开销?我已经尝试了%config / my%config的所有组合并导出%config但没有成功。

非常感谢任何帮助

最佳, 马库斯

1 个答案:

答案 0 :(得分:3)

您的构造函数是继承的,因此工作正常。什么不起作用是你使用%config,它在每个包中单独存在。因为您正在调用基类中定义的构造函数,所以使用了%config的版本。在您的特定情况下,配置哈希是不必要的,因为您可以使用传递给构造函数的name变量来初始化$class成员:

sub new {
    my $class = shift;
    my $self = { };     # initialize the object as a reference to an empty hash
    $self->{"name"} = $class;
    bless ($self, $class);
    return $self;
};

这将起作用(虽然这是不必要的;你总是可以使用Scalar::Util::blessed获取对象的类)。

但更常见的问题似乎是如何在继承的构造函数中使用特定于类的配置信息。一种方法是使用单独的初始化步骤,可以在子类中重写。

package tstbase;

# we don't use Exporter for OO code; exporting methods is highly counterproductive.
# we should also turn on strict and warnings.
use strict;
use warnings;

my %config = (
    "class" => "tstbase",
);

sub new {
    my $class = shift;
    my $self;
    bless $self, $class;
    $self->_init( %config );
    return $self;
};

sub _init { 
    my $self = shift;
    my %args = @_;
    $self->{name} = $args{class};
}

1;

然后:

package tstsubclass;
use parent 'tstbase';   # we have to say what class we're extending

my %config = (
  "class" => "tstsubclass",
);

sub _init { 
    my $self = shift;
    $self->SUPER::_init( %config );
}

1;

在这种情况下,子类的_init方法将由父类中的构造函数调用,该类调用父类的_init方法,但传入其本地%config

处理此问题的更简单方法是使用mixins或Moose角色。