【问题标题】:Variable/subroutine inheritance in parent/child structure父/子结构中的变量/子程序继承
【发布时间】:2012-02-14 22:21:09
【问题描述】:

我有一个父包和几个子孙包:

#parent
package Mother;

sub new {
    my ($class, $args) = @_;
    my $self = bless {}, $class;
    return $self;
}

# load sub...
sub getGrandchildren {
    my ($self, $package) = @_;
    # find all grandchildren dynamicly
    my @grandchildren = ('Mother::Child::Grandchild');

    # load all found packages and load their config
    foreach my $grandchild (@grandchildren) {
        # require etc

        # load config
        my $c = $grandchild->getConfig();

        # damn ... $c is undef
        # I expected { x => 2 } from grandchild
        warn Dumper $c;

        $config{$grandchild} = $c;
    }
}

# this subroutine should be used
# by children and grandchildren
sub getConfig {
    my ($self) = @_;
    use no strict 'refs';
    return ${$self::."config"};
}
1;

# child
package Mother::Child;
use parent qw/Mother/;

our $config = { x => 1 };

sub new { 
    my ($class, $args) = @_;
    my $self = $class->SUPER::new($args);
    $self->getGrandchildren(__FILE__);

    return $self;
}
1;    

# grandchild
package Mother::Child::Grandchild;
use parent qw/Mother::Child/;

our $config = { x => 2 };

sub new { 
    my ($class, $args) = @_;
    my $self = $class->SUPER::new($args);

    return $self;
}
1;

如果我这样称呼:

my $child = Mother::Child->new();

所有孙子都已加载,并且应该加载他们的配置。

我试图通过一个仅在父级中定义的子例程“getConfig()”来实现这一点。

问题是使用

加载配置
$grandchild->getConfig();

返回 undef。

我想避免在每个孩子和孙子中创建一个子例程 getConfig() 来返回正确的配置(从孩子或孙子)。

这种子/孙结构可以做到这一点吗?还是我做错了什么?

解决方案

按照@bvr 的建议,我用 ${$self."::config"} 替换了 getConfig 中的返回值,并添加了“no strict 'refs'”。

【问题讨论】:

  • 你想创建某种树结构,我猜?如果是这样,为什么不只拥有一个Node 类并担心每个特定节点是否有父节点、子节点等?事实上,为什么不使用(或构建)诸如 Tree 之类的 CPAN 模块?
  • “节点类”是什么意思?我对 Perl 很陌生,我不知道 Tree。另一方面,我只想要一个基本的父子结构,“使用父...”就足够了。
  • 如果您要对树进行建模,那么不要尝试为每一代制作单独的包(...Mother::Child::Child 类或 Mother::Child::Child::Child 类呢, ETC?)。只需拥有一堆节点并担心它们之间的关系。我建议您查看 Tree 或 Tree::Simple
  • 哦,请确保始终、始终、始终 use strict;use warnings;。每一个。单身的。时间。
  • 谢谢。我使用警告和严格。总是:)。

标签: perl inheritance parent-child


【解决方案1】:

您的代码有一些问题:

  • Mother::Child 的构造函数不返回$self,因此您无法从Mother::Child::Grandchild->new 调用中获得正确的引用。
  • $self::config 访问包变量的语法不正确。你需要这样的东西:

     sub getConfig {
         my ($self) = @_;
         my $class = ref $self;
    
         no strict 'refs';
         return ${$class . "::config"};
     }
    
  • getGrandchildren 获取配置错误 - 例如,您在其中获取变量 @grandchildren

编辑:no strict 'refs' 添加到getConfig 子例程以在本地禁用此检查。

【讨论】:

  • 我在代码示例中添加了“return $self”并定义了@grandchildren 数组。那只是拼写错误,我的应用程序代码中有。
  • 返回 ${$class 。 "::配置"};给我这个:“在使用“严格引用”时,不能使用字符串(“::config”)作为标量引用”。 $class 为空。
  • $class 显然是空的,因为 ref($self) 不返回任何内容。 getConfig() 中的 $self 只是一个字符串“Mother::Child::Grandchild”,而不是一个对象。我显然做错了什么......并使用 ${$self 。 "::配置"};给出相同的错误:不能使用字符串 ("Mother::Child::Grandchild::config") 作为 SCALAR ref while "strict refs" in use"
  • @toktok - 所以你不想在实例上调用getConfig 作为方法?在这种情况下,最好避免将其命名为$self。对于问题的另一部分,您可以仅对本地范围禁用严格。请参阅我的答案中的更新。
  • 非常感谢。 “我的 $class= ref $self”始终为空。我删除了它,现在我返回 ${$self 。 "::配置"};虽然我不确定这里发生了什么以及为什么严格的抱怨,但这很有效。
猜你喜欢
  • 2021-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-17
  • 1970-01-01
  • 2023-03-27
相关资源
最近更新 更多