首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >防止Moose抽象类的实例化

防止Moose抽象类的实例化
EN

Stack Overflow用户
提问于 2017-11-03 20:13:08
回答 2查看 289关注 0票数 1

我使用Perl和Moose,必须防止抽象类的实例化。

该项目正处于相当高级的阶段--对Moose::RoleMooseX::*来说太晚了。

我正在考虑根据BUILDARGS中的类名检查包名,并在匹配的情况下调用die

这种方法有什么问题吗?

代码语言:javascript
复制
package Foo::Abstract {

    use Moose;

    has 'test' => ( isa => 'Int', is => 'rw', default => '0' );

    around BUILDARGS => sub {
        die if $_[1] eq __PACKAGE__;
        $orig  = shift;
        $class = shift;
        $class->$orig( @_ );
    };

    no Moose;
}

package Foo::Concrete {

    use Moose;

    extends 'Foo::Abstract';

    no Moose;
}

use Test::More;
use Test::Exception;

dies_ok { Foo::Abstract->new() } "cannot instantiate. OK";

my $c;
lives_ok { $c = Foo::Concrete->new() } "instantiated Foo::Concrete. OK";

ok( 0 == $c->test );

done_testing();
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-11-08 19:44:41

正如一些人在评论中指出的那样,您可能应该使用一个角色,并在每个“子类”中进行更改来完成组合。然而,您为懒惰提出了一个令人信服的论点(在重构过程中,在一个地方进行了一次更改)。

我的建议是“两者兼得”。将您希望抽象出来的现有类重构为一个角色:

代码语言:javascript
复制
mv lib/Foo/Abstract.pm lib/Foo/Role/Interface.pm; 
perl -pie's/\bFoo::Abstract\b/Foo::Role::Interface/g' !$

然后在一个新的Foo::Abstract中只需做:

代码语言:javascript
复制
package Foo::Abstract;
use Moose;
with qw(Foo::Role::Interface);
around BUILDARGS => sub { 
    $_[1] ne __PACKAGE__ ? shift->(@_) : die __PACKAGE__ . 'is ABSTRACT';
}
1;

这样,随着时间的推移,您可以慢慢地用更合适的extends qw(Foo::Abstract)来替换with qw(Foo::Role::Interface),但不必预先支付所有的费用。您甚至可以在Foo::Abstract中记录这是计划,以便其他开发人员来帮助进行转换。

票数 1
EN

Stack Overflow用户

发布于 2017-11-08 16:56:36

怎么会太晚才使用角色呢?只需替换:

代码语言:javascript
复制
use Moose;

使用

代码语言:javascript
复制
use Moose::Role;

在Foo中::混凝土,替换

代码语言:javascript
复制
extends 'Foo::Abstract';

使用

代码语言:javascript
复制
with 'Foo::Abstract';
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47103787

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档