Perl:对基类和子类使用通用构造函数 [英] Perl: Using common constructor for base and subclass

查看:226
本文介绍了Perl:对基类和子类使用通用构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to initialize a base class and a subclass without having to copy the constructor. This is what I got:

tstbase.pm:

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:

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的outout是

The outout of tst.pl is

Testbase tstbase
Testsubclass tstbase

寻找

Testbase tstbase
Testsubclass tstsubclass

这是我将sub new {..}例程复制到tstsubclass.pm时得到的。有没有办法避免开销?我尝试所有的组合的%config /我们的%配置和导出%配置没有成功。

which I get when I copy the "sub new { .. }" routine over to tstsubclass.pm. Is there a way to avoid that overhead? I have tried all combinations of my %config / our %config and exporting %config with no success.

任何帮助非常感谢

Best,
Marcus

Best, Marcus

推荐答案

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

Your constructor is inherited, so that's working fine. What's not working is your use of %config, which exists separately in each package. Because you're calling the constructor defined in your base class, that version of %config is used. In your specific case, the config hash is unnecessary, since you can just initialize the name member by using the $class variable passed in to your constructor:

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

This will work (although it's unnecessary; you can always get the class of an object using Scalar::Util::blessed).

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

But the more general question appears to be about how to use class-specific configuration information in an inherited constructor. One way to do it would be to use a separate initialization step which can be overridden in the child class.

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

In this case, your subclass's _init method will get called by the constructor in the parent class, which calls the parent class's _init method, but passing in its local %config.

更容易的方法是使用mixins或Moose角色。

An easier way to handle this would be to use mixins, or Moose roles.

这篇关于Perl:对基类和子类使用通用构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆