【发布时间】:2011-06-03 13:41:24
【问题描述】:
我有一个基类和十几个派生类。除一个派生类外,所有派生类都需要一个名为key 的属性。所以我可以将它添加到 11 个派生类中,而将第 12 个单独保留。
但是,懒惰就是这样,我想将属性添加到基类中,从而避免重复声明 11 次,并添加我认为的一致性和简单性。
现在,这对不需要 key 属性的一类造成了问题。请注意,如果这个类有这个属性并没有什么坏处,但它并不需要它。
我的想法是通过使用标志方法is_strict 来解决此问题,该方法将从BUILDARGS 调用以决定是否需要key。这是一个简单的脚本来说明这一点(好吧,我颠倒了这个概念,key 属性仅在一种情况下需要(而不是在所有情况下都需要),但问题仍然受到这种颠倒的影响):
#!perl
package Bla;
use Moose;
use Carp ();
has grop => is => 'ro', isa => 'Str'; # optional
has key => is => 'ro', isa => 'Int'; # required in all but one cases
# required => should depend on $class->is_strict;
sub is_strict { 0 } # not strict by default as per this base class
# imagine a bunch of other stuff here shared by all derived classes
around BUILDARGS => sub {
my $orig = shift;
my $class = shift;
my $args = @_ == 1 ? shift : { @_ };
Carp::croak 'key missing'
if not exists $args->{key}
and $class->is_strict;
return $class->$orig( @_ );
};
no Moose; __PACKAGE__->meta->make_immutable;
package Bla::Eins;
use Moose; extends 'Bla';
no Moose; __PACKAGE__->meta->make_immutable;
package Bla::Zwei;
use Moose; extends 'Bla';
no Moose; __PACKAGE__->meta->make_immutable;
package Bla::Drei;
use Moose; extends 'Bla';
override is_strict => sub { 1 }; # but here it is required
no Moose; __PACKAGE__->meta->make_immutable;
package main;
use Test::More;
use Test::Exception;
lives_ok { Bla::Eins->new };
lives_ok { Bla::Zwei->new };
throws_ok { Bla::Drei->new } qr/key missing/;
lives_ok { Bla::Drei->new( key => 99 ) };
done_testing;
这可行,但有没有更好的方法来实现我想要的?
【问题讨论】: