2011-07-14 80 views
3

我想用一個更具體的子類來繼承和擴展一個基類,該子類從訪問器中移除必需的屬性並指定一個懶惰構建的默認值。但是,這樣做時,派生類不再圍繞調用訪問器的周圍子例程。修改繼承的訪問器並保留修飾符

我在做什麼錯在我的定義?

編輯:我應該說,我可以簡單地繼承訪問器而不修改它,並且around修飾符仍然有效,我知道我可以做一些事情,比如設置訪問器來獲取getter,然後定義一個getter方法訪問者的名稱(即sub attr { my $self = shift; my $value = $self->_get_attr; return "The value of attr is '$value'"; })。我只是很驚訝周圍的修改器被輕易地拋棄。

use strict; 
use warnings; 
use 5.010; 

package My::Base; 
use Moose; 

has 'attr' => (is => 'ro', isa => 'Str', required => 1); 

around 'attr' => sub { 
    my $orig = shift; 
    my $self = shift; 

    my $response = $self->$orig(@_); 
    return "The value of attr is '$response'" 
}; 

package My::Derived; 
use Moose; 

extends 'My::Base'; 

has '+attr' => (required => 0, lazy_build => 1); 

sub _build_attr { 
    return "default value"; 

} 

package main; 

my $base = My::Base->new(attr => 'constructor value'); 
say $base->attr; # "The value of attr is 'constructor value'" 

my $derived = My::Derived->new(); 
say $derived->attr; # "default value" 

回答

0

每從stvn爲same question on perlmonks的響應,問題是:

其實,它不是去掉「圍繞」修飾,你只是 創建一個新的訪問在派生類中,這本身並不是 左右。請允許我解釋...

當您創建一個屬性時,Moose將編譯 的訪問器方法,並將它們安裝到定義它們的包中。這些 訪問器方法沒有什麼神奇的(事實上,Moose中沒有任何東西是非常神奇的,複雜的,但是不可思議的),所以它們按子類繼承 ,就像任何其他方法一樣。

當你在某個方法的「周圍」時(就像你在這裏做的那樣),駝鹿會從包中提取 這個子包,包裝它並用 包裝的版本替換原件。這一切只發生在本地包中, 方法修飾符不知道(或關心)有關繼承的任何事情。

當您更改使用+ ATTR形式的屬性定義,駝鹿 查找超類列表屬性元對象,然後 克隆該屬性元對象,將您要求 更改,然後將安裝屬性進入當地班級。結果是 所有訪問方法都被重新編譯到本地類中,因此覆蓋了超類中定義的方法。

它不會反過來,其中訪問器是從ISA中最底層的類構建而來,然後依次應用ISA堆棧中的左邊修飾符。