如何设置可由同一基类(Perl/Moose)的所有子类访问的静态变量?

qod*_*nja 7 oop perl static moose

由于Perl/Moose在调用子类BUILD函数之前总是调用基类的BUILD函数,因此每次实例化子类时都会有一个新的基类实例.

如何创建可供所有子类使用的静态变量,或者如何创建静态基类或抽象类?(这种做法有意义吗?)

我正在尝试创建一个变量,该变量动态启用或禁用在基类中运行时定义但可从子类访问的函数的某些功能.

所以,如果我做了类似的事情

my obj = My::childObject_1->new( 'use_my_var' => 1 );
Run Code Online (Sandbox Code Playgroud)

它也是如此

my obj2 = My::childObject_2->new();
my obj3 = My::childObject_3->new();
Run Code Online (Sandbox Code Playgroud)

无需专门定义该变量.除非

my obj4 = My::childObject_2->new( use_my_var' => 0 ); 
Run Code Online (Sandbox Code Playgroud)

在这种情况下,对于所有子类,从那一点起它将是假的,因为它们都是

extends My::BaseObject
Run Code Online (Sandbox Code Playgroud)

另外,是否有描述此行为的设计模式?

(注意:我在共享系统上,所以我无法安装MooseX - 或者至少我无法弄清楚如何在我的用户目录中设置本地PERL5LIB模块安装= /所以只有Moose解决方案现在有帮助!)

Eva*_*oll 10

UPDATE

现在有一个很大更好的方式来做到这一点,使用MooseX :: ClassAttribute

然后只使用class_has而不是has您希望与所有实例共享的方法.

package My::Class;

use Moose;
use MooseX::ClassAttribute;

class_has 'Cache' =>
    ( is      => 'rw',
      isa     => 'HashRef',
      default => sub { {} },
    );

__PACKAGE__->meta()->make_immutable();
Run Code Online (Sandbox Code Playgroud)

另外,是否有描述此行为的设计模式?

是.它被称为Singleton.Singleton是一种模式,其中多个启动(调用->new)将返回相同的对象.您可以这样做,也可以将变量存储在类之外.Moose提供了一个允许你轻松创建Singletons的层(认为这不是特别困难):模块MooseX :: Singleton.Moose还允许您使用访问者委托给另一个对象.

这里我们使用MooseX :: Singleton,并将delgation设置为隐藏属性以获得所需的效果.

package MySingleton;
use MooseX::Singleton;

has 'foo' => ( is => 'rw', isa => 'Bool', default => 0 );

package ClassA;
use Moose;

has '_my_singleton' => (
  isa => 'MySingleton'
  , is => 'ro'
  , default => sub { MySingleton->new }
  , handles => [qw( foo )]
);


package ClassB;
use Moose;

has '_my_singleton' => (
  isa => 'MySingleton'
  , is => 'ro'
  , default => sub { MySingleton->new }
  , handles => [qw( foo )]
);

package main;
use Test::More tests => 5;

my $class_a = ClassA->new;
my $class_b = ClassA->new;

is( $class_a->foo(0), 0, 'Set A to false' );
is( $class_a->foo, 0, 'A Is false' );
is( $class_b->foo, 0, 'B Is false' );
is( $class_b->foo(1), 1, 'Set B to true' );
is( $class_a->foo, 1, 'A is true' );
Run Code Online (Sandbox Code Playgroud)

或者,没有MooseX

除非有要求,否则请不要这样做.MooseX方法更好:

package Underclass;
use Moose;

has 'foo' => ( is => 'rw', isa => 'Bool', default => 0 );

package SingletonWrapper;
my $obj;
sub new {
    if ( $obj ) { return $obj; }
    else { $obj = Underclass->new }
}

package ClassA;
use Moose;

has '_my_singleton' => (
    isa => 'Underclass'
    , is => 'ro'
    , default => sub { SingletonWrapper->new }
    , handles => [qw( foo )]
);


package ClassB;
use Moose;

has '_my_singleton' => (
    isa => 'Underclass'
    , is => 'ro'
    , default => sub { SingletonWrapper->new }
    , handles => [qw( foo )]
);
Run Code Online (Sandbox Code Playgroud)