2013-09-23 51 views
6

我想實現一個Moose :: Role類,它的行爲就像在Java中的一個抽象類。我想在角色中實現一些方法,但是有能力在具體類中重寫這些方法。如果我使用與擴展類相同的樣式來嘗試此操作,則會收到錯誤Cannot add an override method if a local method is already present。這裏有一個例子:如何覆蓋Moose :: Role中的子項?

我的抽象類:

package AbstractClass; 

use Moose::Role; 

sub my_ac_sub { 

    my $self = shift; 

    print "In AbstractClass!\n"; 
    return; 
} 

1; 

我的具體類:

package Class; 

use Moose; 

with 'AbstractClass'; 

override 'my_ac_sub' => sub { 

    my $self = shift; 

    super; 
    print "In Class!\n"; 
    return; 
}; 

__PACKAGE__->meta->make_immutable; 
1; 

然後:

use Class; 

my $class = Class->new; 
$class->my_ac_sub; 

難道我做錯了什麼?我正在努力完成的工作應該以不同的方式完成?我試圖不應該做什麼?

+0

使用抽象類來模擬抽象類!這隻需要你使建設變得不可能(即提供一個會引發錯誤的BUILDALL)。 – amon

+1

可能這樣做的駝鹿方式是在角色中有'需要'my_ac_sub';',而不是'虛擬'方法。 Moose :: Role將會檢查它是否已經用可用的方法組合成一個類, –

+1

我試着運行代碼,然後用'sub my_ac_sub'替換重寫,並突然它按照預期工作。那個「修復」有什麼問題嗎? (免責聲明:我是Moose新手)。 – Dallaylaen

回答

4

原來我用它不正確。我打開a ticket,並證明這樣做的正確方法:

package Class; 

use Moose; 

with 'AbstractClass'; 

around 'my_ac_sub' => sub { 

    my $next = shift; 
    my $self = shift; 

    $self->$next(); 
    print "In Class!\n"; 
    return; 
}; 

__PACKAGE__->meta->make_immutable; 
1; 

這種變化對預期的效果。

2

Some time ago,我這樣做是由一個僅由requires聲明組成的角色完成的。這構成了抽象基類。然後,你可以把你的默認實現在另一個類和繼承:

#!/usr/bin/env perl 

use 5.014; 

package AbstractClass; 

use Moose::Role; 

requires 'my_virtual_method_this'; 
requires 'my_virtual_method_that'; 

package DefaultImpl; 

use Moose; 
with 'AbstractClass'; 

sub my_virtual_method_this { 
    say 'this'; 
} 

sub my_virtual_method_that { 
    say 'that' 
} 

package MyImpl; 

use Moose; 
extends 'DefaultImpl'; 
with 'AbstractClass'; 

override my_virtual_method_that => sub { 
    super; 
    say '... and the other'; 
}; 

package main; 

my $x = MyImpl->new; 

$x->my_virtual_method_this; 
$x->my_virtual_method_that; 

如果你想爲只有幾個方法中的角色定義提供默認的實現,從DefaultImpl刪除requires

輸出:

$ ./zpx.pl 
this 
that 
... and the other
+1

我認爲這是一個很好的解決方法。它不「感覺乾淨」,但我會爲此提交一份願望清單增強。謝謝你的回答。 – Joel