如何在面向对象的perl中处理这种情况

时间:2010-06-21 11:24:40

标签: perl

package a::b::c:d

my $res =  a::b::c:e->new(); # i am doing like this
# is there any othere to do this

sub new {
...
 my $self = { 
     #result = a::b::c:e->new();
  }
}

sub test {
}

sub test2 {
}


1;

package a::b::c:e

sub new {
...
}

sub testresult {
}
1;

我的问题是:

  • 如何在新版本中初始化e中的d模块,而不是创建每个函数,

  • 如何使用它将一些结果存储到e:testresult

2 个答案:

答案 0 :(得分:2)

有两种策略 - 检查符号表以在创建时初始化,或者使用AUTOLOAD并使用can进行测试。 AUTOLOAD可能比较麻烦,因为你必须处理方法不存在的情况:

sub AUTOLOAD {
    my $self = shift;

    my $method = $AUTOLOAD;
    $method =~ s/.*://;   # strip package name

    if ( $self->{'result'}->can($method) ) {
        return $self->{'result'}->$method(@_);
    } else {
        croak "Unknown method : $method";
    } 
}  

但符号表技巧很脆弱,好像他们正在使用继承,你也不会看到继承的方法而没有走上@ISA。 (即使他们不是 - 他们可能会在未来开始使用继承,这会导致事情破裂)

...

通常,当您尝试复制其他模块的界面时,您有一个继承案例,因此您可能想问自己::d::e之间的关系:< / p>

  • a::b::c::da::b::c::e
  • a::b::c::d使用a::b::c::e

如果它是一个is-a关系,它通常更适合继承(尽管你可能有每个方法的包装器,但仍然需要完成整个练习)。如果它是一个使用关系,你可能不希望从它们拥有的每一个方法继承,并且只能对列表进行硬编码(尽管如果使用的类被更新,列表可能会改变)

foreach my $method ( @list_of_methods_to_copy ) {
    *{$method} = sub {
        my $self = shift;
        return $self->{'results'}->$method(@_);
    }
}

答案 1 :(得分:0)

如果您没有在两个类之间寻找继承,那么在我看来您可能希望使用Class::Delegator来编写您的类。这样,您可以通过在a::b::c::d中添加以下内容来创建委派例程。

use Class::Delegator send => 'testresult', to => '{result}';

但是你还需要修复你的构造函数:

my $self 
    = bless { 
        result => a::b::c::e->new()
    }, $class_name
    ;
return $self;

完成后,您将有一个字段'{result}'委托给。