2017-11-03 14 views
1

저는 Perl을 무스와 함께 사용하고 있으며 추상 클래스의 인스턴스화를 방지해야합니다.무스 추상 클래스의 인스턴스화 방지

프로젝트가 상당히 발전된 단계 - 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(); 
+4

이 문제를 해결하는 방법은 역할입니다. – AKHolland

+2

"Moose :: Role"에 대해 "너무 늦음"이 될 수는 없습니다. – Borodin

+0

[weak_ref 옵션] (https://metacpan.org/pod/distribution/Moose/lib/Moose/Manual/Attributes.pod#Weak-references)을 사용할 수 있어야하지만 AKHolland와 Borodin에 동의합니다. 역할에 시간을 할애해야합니다. – interduo

답변

1

으로 여러 사람이 의견에서 지적

extends 'Foo::Abstract'; 

로 교체하면 아마도 이어야합니다. 역할을 사용하고 모든 "하위 클래스"에서 구성을 변경해야합니다. 그러나 당신은 게으름에 대한 강력한 논쟁을하고 있습니다 (리펙터 중 한 곳에서 하나의 변경).

제 제안은 "둘 다"입니다. 당신은 천천히 더 적절한으로 시간이 지남에 extends qw(Foo::Abstract)을 대체 할 수

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

이 방법 : 역할로 아웃 추상적되고 싶어 기존의 클래스를 리팩토링 : 새 Foo::Abstract에 그런

mv lib/Foo/Abstract.pm lib/Foo/Role/Interface.pm; 
perl -pie's/\bFoo::Abstract\b/Foo::Role::Interface/g' !$ 

단순히 않는다 with qw(Foo::Role::Interface)하지만 그 모든 비용을 앞에 물지 않아도됩니다. 이 계획이 Foo::Abstract에 있음을 문서화하여 다른 개발자가 함께 도움을 받도록 할 수도 있습니다.

1

어떻게 역할을 사용하기에는 너무 늦습니까? 그냥 교체 : 콘크리트 ::

use Moose; 

use Moose::Role; 

와 푸에

with 'Foo::Abstract';