Perl:使用子类中的常量实例化复杂数据结构

Perl:使用子类中的常量实例化复杂数据结构,perl,constants,subclass,instantiation,Perl,Constants,Subclass,Instantiation,我有一个基类,它是用一个复杂的数据结构实例化的,有三位数的条目,所有条目都是常量。其中一些常量是特定于类的,应该用不同的常量实例化。我很难做到这一点。归结起来就是: tstbase.pm: package tstbase; my $THISCLASSCONSTANT = "baseconstant.2"; my %complexdatastructure = ( "attribute.1" => "baseconstant.1", "attribute.2" =>

我有一个基类,它是用一个复杂的数据结构实例化的,有三位数的条目,所有条目都是常量。其中一些常量是特定于类的,应该用不同的常量实例化。我很难做到这一点。归结起来就是:

tstbase.pm:

package tstbase;

my $THISCLASSCONSTANT = "baseconstant.2";
my %complexdatastructure = (
    "attribute.1" => "baseconstant.1",
    "attribute.2" => $THISCLASSCONSTANT,
);

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

sub _init {
    my $self = shift;
    $THISCLASSCONSTANT = shift;
    foreach (keys %complexdatastructure) {
        $self->{$_} = $complexdatastructure{$_};
    };
};
tstsubclass.pm:

package tstsubclass;

use parent "tstbase";
my $THISCLASSCONSTANT = "subclassconstant.2";

sub _init {
    my $self = shift;
    $self->SUPER::_init( $THISCLASSCONSTANT );
};
tst.pl:

#!/usr/bin/perl

use tstbase;
use tstsubclass;

my $baseobj = tstbase->new;
print "Testbase ".$baseobj->{"attribute.1"}." ".$baseobj->{"attribute.2"}."\n";

my $subobj = tstsubclass->new;
print "Testsubclass ".$subobj->{"attribute.1"}." ".$subobj->{"attribute.2"}."\n";
现在输出是

Testbase baseconstant.1 baseconstant.2
Testsubclass baseconstant.1 baseconstant.2
而我希望它是

Testbase baseconstant.1 baseconstant.2
Testsubclass baseconstant.1 subclassconstant.2
可能吗?我很乐意使用

sub THISCLASSCONSTANT = { "subclassconstant.2" }
如果有帮助的话。tstsubclass不应具有任何基本常量值。 现在,我用魔术字符串实例化这个类,并进行搜索和替换。它可以工作,但似乎不那么优雅和性能

非常感谢您的帮助。我以前问过这个问题(),但过度简化了示例,因此回答只能暗示可能的解决方案

谢谢,
Marcus

最简单的方法是使用
%complexdatastructure
中的引用。 但请注意,执行此操作时,
$thisclassconts
将在第一次调用
tstsubclass->new
后更改

package tstbase;

my $THISCLASSCONSTANT = "baseconstant.2";
my %complexdatastructure = (
    "attribute.1" => \ "baseconstant.1",
    "attribute.2" => \ $THISCLASSCONSTANT,
);

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

sub _init {
    my $self = shift;
    $THISCLASSCONSTANT = shift;
    foreach (keys %complexdatastructure) {
        $self->{$_} = ${$complexdatastructure{$_}};
    };
};
现在您的输出是所需的,但是如果您像这样更改新调用的顺序:

my $subobj = tstsubclass->new;
print "Testsubclass ".$subobj->{"attribute.1"}." ".$subobj->{"attribute.2"}."\n";

my $baseobj = tstbase->new;
print "Testbase ".$baseobj->{"attribute.1"}." ".$baseobj->{"attribute.2"}."\n";
您将获得:

Testsubclass baseconstant.1 subclassconstant.2
Testbase baseconstant.1 subclassconstant.2
您现在可以做的是编写“自己的”小
local
(我不知道为什么正常的
local
即使将
$THISCLASSCONSTANT
的声明更改为
我们的
,也不起作用)

tstbase::_init
更改为:

sub _init {
    my $self = shift;
    my $oldconstant = $THISCLASSCONSTANT;
    $THISCLASSCONSTANT = shift;
    foreach (keys %complexdatastructure) {
        $self->{$_} = ${$complexdatastructure{$_}};
    };
    $THISCLASSCONSTANT = $oldconstant;
};

现在我想你得到了你想要的。

你从来没有使用过
$THISCLASSCONSTANT
!(您缺少了我的
my
,因此您不小心用该名称重击了现有的var,而不是创建了一个新的var。)我们的目标是使用不带参数的“new”,并让类仅根据自身进行实例化。也许我不清楚您是否从未使用传递给
\u init
$thisclassconts
。这与
new
无关。我想这是我的问题-我应该在哪里传递什么以实现所需的输出,同时避免更改tst.pl并避免将%complexDataStratstructure复制到tststsubClassThank,这显然是个难题。我在foreach循环中添加了一点代码,这样它既可以处理引用也可以处理非引用,这样我就不必更改模块中的所有%complexdatastructure-s:
if(ref($complexdatastructure{$})){
$self->{$}=${$complexdatastructure{$};}else{$self->{${}=$complexdatastructure{$};};`如果你喜欢brefity,你也可以在循环中执行
$self->{$}=ref${$}$}${$complexdatastructure{$}:$complexdatastructure{$};
(对不起,如果错了,在我的手机上).实际上我已经这么做了-在使用if then else多年后,我给了三元运算符另一个机会,这是我更改的代码之一。我还不确定它是否更易于阅读,但它确实更易于键入(尤其是在手机上^^)