2016-08-07 19 views
6

ロールの属性を上書きしてデフォルトを提供することはできますか?ロールの属性を上書きする

role A { 
    has $.a; 
} 
class B does A { 
    has $.a = "default"; 
} 
my $b = B.new; 

これは、コンパイルエラーが生じる:

===SORRY!=== Error while compiling: 
Attribute '$!a' already exists in the class 'B', but a role also wishes to compose it 

答えて

5

Rにおける方法は$!aを参照することができるので呼ばれるもの属性曖昧さが存在することになります。

継承/混合属性を初期化するためにサブメソッドBUILDを使用します。

role R { has $.a }; 
class C does R { 
    submethod BUILD { $!a = "default" } 
}; 
my $c = C.new; 
dd $c; 
# OUTPUT«C $c = C.new(a => "default")␤» 

用途によっては、ロールパラメータを使用してデフォルトを設定するほうがよい場合があります。

role R[$d] { has $.a = $d }; 
class C does R["default"] { }; 
my $c = C.new; 
dd $c; 
# OUTPUT«C $c = C.new(a => "default")␤» 
+2

"Rのメソッドは$!aを参照する可能性があるので、どの属性が参照されているかはあいまいです。" OPのアプローチがうまくいかない理由や、最初の解決策でも発生し、2番目の解決策(パラメトリックな役割の使用)によって解決される問題については、それが話していますか? – raiph

1

いいえ、それは属性を再宣言することはできません - しかし、あなたは、クラスのBUILDサブメソッド使用してそれを初期化することができます:あなただけBUILDの本体内に値を設定した場合、その

role A { 
    has $.a; 
} 

class B does A { 
    submethod BUILD(:$!a = 'default') {} 
} 

注意を代わりに

class B does A { 
    submethod BUILD { $!a = 'default' } 
} 

を経由してその署名のユーザーがB.new(a => 42)経由という名前の初期化子を提供することで、デフォルトを上書きすることはできません。

デフォルトの設定は、あなたが多くを行うことを期待する何か(デフォルト値は、役割のインタフェースの一部とみなすことができるIE)そのパラメータ作っている場合に特に有用な別の、よりエレガントなアプローチ:

role A[$d] { 
    has $.a = $d; 
} 

class B does A['default'] {} 
関連する問題