Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 防止Moose抽象类的实例化_Perl_Abstract Class_Moose - Fatal编程技术网

Perl 防止Moose抽象类的实例化

Perl 防止Moose抽象类的实例化,perl,abstract-class,moose,Perl,Abstract Class,Moose,我将Perl与Moose一起使用,必须防止抽象类的实例化 该项目处于相当高级的阶段-对于Moose::Role或MooseX::*来说太晚了 我正在考虑在BUILDARGS中对照类名检查包名, 如果有匹配项,则调用die 这种方法有什么问题吗 package Foo::Abstract { use Moose; has 'test' => ( isa => 'Int', is => 'rw', default => '0' ); around

我将Perl与Moose一起使用,必须防止抽象类的实例化

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

我正在考虑在
BUILDARGS
中对照类名检查包名, 如果有匹配项,则调用
die

这种方法有什么问题吗

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();

使用角色怎么太迟了?只需替换:

use Moose;

在Foo::Concrete中,替换

extends 'Foo::Abstract';


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

我的建议是“两个都做”。将要抽象出来的现有类重构为角色:

mv lib/Foo/Abstract.pm lib/Foo/Role/Interface.pm; 
perl -pie's/\bFoo::Abstract\b/Foo::Role::Interface/g' !$
然后在新的
Foo::Abstract
中,只需执行以下操作:

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

通过这种方式,您可以慢慢地将
扩展qw(Foo::Abstract)
替换为更合适的
扩展qw(Foo::Role::Interface)
,但不必预先承担所有成本。您甚至可以在
Foo::Abstract
中记录这是一个计划,以便其他开发人员帮助转换。

角色是解决此问题的方法。我不认为对
Moose::Role
来说“为时已晚”。您可以使用,但是我同意阿克霍兰德和博罗丁的观点,你需要为角色腾出时间。阿克霍兰德,博罗丁,国际都灵。Moose::角色是正确的方法。但这是现实生活中的情况。添加
die if$\uuu[1]eq\uuuuu包\uuuuuu是一个包中的一行修改。将
扩展PackageName
替换为
扩展PackageName
,并将
添加到许多软件包中需要方法\u name
,测试、调试。。。重构需要时间。如果编写了正确的测试,测试部分应该调用
prove
。:-)
mv lib/Foo/Abstract.pm lib/Foo/Role/Interface.pm; 
perl -pie's/\bFoo::Abstract\b/Foo::Role::Interface/g' !$
package Foo::Abstract;
use Moose;
with qw(Foo::Role::Interface);
around BUILDARGS => sub { 
    $_[1] ne __PACKAGE__ ? shift->(@_) : die __PACKAGE__ . 'is ABSTRACT';
}
1;