【问题标题】:In Perl/Moose, how do you create a static variable in a parent class that can be accessed from subclasses?在 Perl/Moose 中,如何在父类中创建可以从子类访问的静态变量?
【发布时间】:2011-09-14 19:40:42
【问题描述】:

我想在基类中定义一个所有子类都可以读取和写入的“注册表”哈希,我如何使用 Moose/Perl 来完成?

【问题讨论】:

    标签: perl static moose


    【解决方案1】:

    这是一个简单的 Perl OO 风格的实现。

    您有两个类,BaseClass 带有全局变量 $REGISTRY,以及 DerivedClass,它继承自 BaseClass$REGISTRY 可以通过registry() 方法从任何类实例中读写。

    #!/usr/bin/env perl
    
    use 5.012;
    use strict;
    
    package BaseClass;
    
    our $REGISTRY = {};
    
    sub new {
        my $class = shift;
        my $self  = {};
        bless $self, $class;
        return $self;
    }
    
    sub registry {
        my $self = shift;
        return $REGISTRY;
    }
    
    package DerivedClass;
    
    push our @ISA, 'BaseClass';
    
    package main;
    
    my $base    = BaseClass->new;
    $base->registry->{ alpha } = 1;
    
    my $derived = DerivedClass->new;
    $derived->registry->{ beta } = 2;
    
    say $_, ' -> ', $base->registry->{ $_ } foreach keys %{ $base->registry };
    

    如果你运行这个程序,你会得到:

    alpha -> 1
    beta -> 2
    

    如果您更喜欢全 Moose 解决方案,您应该试试这个:

    #!/usr/bin/env perl
    
    use 5.012;
    use strict;
    
    package BaseClass;
    use Moose;
    
    our $_REGISTRY = {};
    has '_REGISTRY' => (
        is      => 'rw',
        isa     => 'HashRef',
        default => sub { return $_REGISTRY }
    );
    
    sub registry {
        my $self = shift;
        return $self->_REGISTRY;
    }
    
    __PACKAGE__->meta->make_immutable;
    no Moose;
    
    package DerivedClass;
    use Moose;
    
    use base 'BaseClass';
    
    __PACKAGE__->meta->make_immutable;
    no Moose;
    
    package main;
    
    my $base    = BaseClass->new;
    $base->registry->{ alpha } = 1;
    
    my $derived = DerivedClass->new;
    $derived->registry->{ beta } = 2;
    
    say $_, ' -> ', $base->registry->{ $_ } foreach keys %{ $base->registry };
    

    它产生与 OO Perl 程序相同的结果。 注意_REGISTRY 属性是如何定义的。 Moose 不喜欢将 refs 作为默认值:default => {} 是被禁止的,您必须将任何引用包装为匿名子例程中的返回值。

    【讨论】:

    • Moose 实际上会阻止 default => {} 以防止此问题成为默认问题。当默认采用裸 ref 时,每个实例都将共享相同的 ref。通过默认评估代码引用,每次都可以创建一个新的引用。在这种情况下,您正在颠覆它并每次都返回相同的 ref。
    【解决方案2】:

    把它实现为一个方法怎么样:

    package BaseClass;
    
    my $hash = {};
    sub registry { $hash };
    

    子类只需使用$self->registry->{$key} 访问值并使用$self->registry->{$key} = $value 设置它们。

    【讨论】:

    • 当我尝试这样做时,子类正在创建他们自己的变量版本......我应该使用一些 SUPER:: descoping 吗?
    • 你的子班有什么进展?我的解决方案与使用全局变量基本相同。
    【解决方案3】:

    【讨论】:

    • @nodebunny,没有 MooseX 这样的东西。你是说 MooseX::ClassAttribute 吗?为什么不能用?
    • @nodebunny,为什么不呢?为什么你可以从 StackOverflow 安装 Perl 代码,但不能从 CPAN 安装?如果我将 MooseX::ClassAttribute 复制到 StackOverflow 会有帮助吗?
    • 因为它是一个共享主机和 id 必须等待他们为每个人安装它
    • @nodebunny,不,您不需要任何特殊权限。您可以将模块安装到任何目录。
    • @nodebunny:查看cgipan 以在您可访问的目录中安装模块。无需询问管理员。
    猜你喜欢
    • 1970-01-01
    • 2011-11-27
    • 2011-03-05
    • 2017-05-21
    • 1970-01-01
    • 1970-01-01
    • 2012-02-04
    • 2014-06-06
    • 1970-01-01
    相关资源
    最近更新 更多