perl – Moose:覆盖派生类中属性的`required`ness

前端之家收集整理的这篇文章主要介绍了perl – Moose:覆盖派生类中属性的`required`ness前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个基类和十几个派生类.除一个派生类之外的所有类都需要名为key的属性.所以我可以将它添加到11个派生类中,并将第12个单独留下.

但是,懒惰就是这样,我想将属性添加到基类中,从而避免重复声明十一次并添加我认为的一致性和简单性.

现在,这对于不需要key属性的一个类造成了问题.请注意,如果此类具有此属性,则不会有任何损害,但它不需要它.

我的想法是通过使用标志方法is_strict解决这个问题,该方法将从BUILDARGS调用以决定是否需要密钥.这是一个简单的脚本来说明这一点(好吧,我颠倒了这个概念,只有一个案例需要关键属性(而不是除了一个案例之外的所有案例),但问题仍然受到这种反转的影响):

#!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;

这有效,但有没有更好的方法来实现我想要的?

解决方法

好吧,我没有尝试过最明显的解决方案,有点愚蠢,只需覆盖派生类中的属性定义,其中必需性与默认值不同.开始了:

#!perl
package Bla;
use Moose;
use Carp ();
has grop => is => 'ro',isa => 'Int'; # required in all but one cases
# imagine a bunch of other stuff here shared by all derived classes
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';
# prefix an attribute you're overriding with a "+" sign
has '+key' => is => 'ro',isa => 'Int',required => 1;
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/\bkey\b.*\brequired\b/;
lives_ok  { Bla::Drei->new( key => 99 ) };
done_testing;

尽管如此,我还是感谢所有的反馈,因为这个Mooseland的包租性比其他语言的对象系统要差.

啊,我已经看到你应该为你用a重写的属性定义作为前缀,所以如果在父类中找不到引用的属性,Moose会可怜地呱呱叫,为你的代码增加了安全性和一致性.我相应地更新了我的示例代码.

猜你在找的Perl相关文章