2013-10-09 11 views
3

我目前正在重構一些代碼,並且正試圖刪除下面的符號引用的用法,用於根據輸入來調度函數。沒有符號引用的調度方法

package Parent; 
use strict; 
use warnings; 

sub dispatch{ 
    my ($self, $funcname) = @_; 


    no strict "refs"; 
    if($self->can($funcname)){ 
    $self->$funcname(); 
    } 
    else{ 
    $self->default_func(); 
    } 
    use strict; 
} 

sub a{ 
    ... 
} 

sub b{ 
    ... 
} 

#...lots more functions... 

sub default_func{ 
    .. 
} 

package Child; 
use strict; 
use warnings; 
use Parent; 

our @ISA = qw(Parent) 

sub c{ 
    .. 
} 

我認爲使用調度表像之下,但這似乎不太理想,因爲有相當複雜與追蹤所有子類和複製所涉及的所有功能一點額外的維護。

package Parent; 
use strict; 
use warnings; 

{ 
    my $funcs ||= { 
    a => sub { shift->a }, 
    b => sub { shift->b }, 
    c => sub { shift->c }, 
    #...lots of functions... 
    DEFAULT => sub {shift->default_func} 
    } 
    sub dispatch{ 
    my ($self, $funcname) = @_; 
    my $func = $funcs->{$funcname} || $funcs->{DEFAULT}; 
    $self->$func(); 
    } 
} 

此外,我認爲轉動調度表來爲成員,這樣的父類不必知道子類的爲好。然後每個子類將自己的函數添加到調度表中。最初我不希望調度表是一個成員,因爲我只想讓它暴露於一個函數,但也許它是不可避免的。但最終將其轉化爲成員並不能解決涉及額外樣板和維護的問題。

有沒有更好的方法?這似乎比符號引用更多的工作。我願意做額外的工作,如果它允許我避免哈克解決方案,但我不知道從這裏走向哪個方向。

+2

在第一個例子中沒有任何符號引用。 '$ self-> can'返回一個代碼引用,'$ self - > $ coderef'在'use strict'下可以正常工作。 – friedo

+3

'$ self - > $ name_of_method()'也可以在'use strict'下正常工作。根本不需要'沒有嚴格的'refs''。 – cjm

+0

我不明白。我使用了一個字符串來代替函數的名字,這會導致perl在其符號表上查找函數名。這不是符號參考的定義嗎? –

回答

3

您的原始代碼示例在use strict下正常工作。 $obj->$method(...)表單不需要符號引用。這是一種廣泛使用的技術,被認爲是良好的做法。

此外,請注意,即使您不得不,也不需要use strict在該函數的結尾處,如在您的示例中。 strict是一個詞彙雜注,所以它的影響無論如何都侷限於它的包含範圍。

0

爲什麼不使用AUTOLOAD?

package Parent; 
use vars qw($AUTOLOAD); 
sub AUTOLOAD { 
    return if $AUTOLOAD =~ m/^.*::(DESTROY)$/; 
    my ($self, @params) [email protected]_; 
    return $self->$AUTOLOAD() if($self->can($AUTOLOAD)){ 
    return $self->default_func(); 
} 
相關問題