2009-08-04 14 views
1

私はモジュールを拡張しています。特別な名前空間の競合:正確には何か、それらを避ける方法。Perlサブクラスでインスタンスデータにアクセスする方法を教えてください。

私はSUPERクラスの変数にアクセスしてアクセッサやオブジェクトメソッドを使ってその状態を変更しないでください。アクセサーがない(または限定された)アクセサがない場合の対処方法これらのオブジェクト変数に直接アクセスすることを「許可」していますか?

乾杯!

答えて

6

スーパークラスの実装が変更されてもサブクラスに影響を与えないようにするため、アクセサを使用してアクセスするのが最善です。あなたはアンダーバーで始まるものから遠く離れた場所にいなければなりません。それらのものはクラスにとってプライベートです。文書化されていないものから遠ざかるようにしてください。それらのことに頼ると、あなたは困ってしまうでしょう。また、has-a対is-a関係の使用を検討してください。

ウィジェットクラスを想像してみましょう。このクラスは、(ノートをこれのどれが特に良いコードではありません、私はちょうど例のためにそれについて考えてとバージョンの投げている)の名前と価格メンバーがあります。

package Widget; 

use strict; 
use warnings; 

sub new { 
    my $class = shift; 
    my %args = @_; 

    return bless { 
     price => $args{price} || 0, 
     name => $args{name} || "unkown", 
    }, $class; 
} 

sub price { shift->{price} } 
sub name { shift->{name} } 

1; 

あなたは、ウィジェットをサブクラス化することを決定しますウェイトメンバーを追加する:

package Widget::WithWeight; 

use strict; 
use warnings; 

use base 'Widget'; 

sub new { 
    my $class = shift; 
    my %args = @_; 
    my $self = $class->SUPER::new(%args); 
    $self->{weight} = $args{weight} || 0; 
    return bless $self, $class; 
} 

sub weight { shift->{weight} } 

sub price_per_pound { 
    my $self = shift; 
    return $self->{price}/$self->{weight}; 
} 

1; 

ここで、最初のモジュールの作成者が価格の保管方法を変更したとします。おそらくそれは、浮動小数点数として格納されていたと著者はペニーの整数としてそれを格納すると良いだろうことに気づい:

突然
package Widget; 

use strict; 
use warnings; 

sub new { 
    my $class = shift; 
    my %args = @_; 

    if ($args{price}) {   
     $args{price} =~ s/[.]//; 
    } 

    return bless { 
     price => $args{price} || "000", 
     name => $args{name} || "unkown", 
    }, $class; 
} 

sub price { 
    my $self = shift; 
    my $price = $self->{price}; 
    substr($price, -2, 0) = "."; 
    return $price; 
} 

sub name { shift->{name} } 

1; 

、あなたのテストが失敗し始めますが、あなたが代わりにpriceアクセサを使用した場合あなたはその変化から隔離されていたでしょう。

+0

> {objnum => NUM、type => TYPE、value => VALUE}、 } $ self - > {property}のように、$ selfを介して直接{property}にアクセスしないでください。それはget_property()アクセサを持っていた場合にのみ私はそれにアクセスする必要がありますか? 私のインストールスクリプトでSUPERクラスモジュールの証明版が必要なのですか? –

+0

アンダーバー(例えば '$ self - > {_ property}')でハッシュに格納されていない場合、それらは公正なゲームですが、アクセサーメソッドはより安全な方法です(実装の変更からあなたを守る)。 –

1

名前空間の競合は、2つのモジュールを1つに継承し、両方が同じサブを提供(エクスポート)する場合に発生します。

クラスとロールを提供するPerlの拡張機能Mooseをご覧ください。ロールを使用すると、多くの競合を避けることができます。 http://www.iinteractive.com/moose/

も参照してください。Mooseはクラス変数の自動アクセサーも作成し、継承クラスからアクセスすることをより安全にします。 現実の値は、このようなハッシュ、参考文献として格納されています: $自己= { 「プロパティを」=私はしかし、私は、例えば、直接、いくつかの変数の内部表現をアクセスしていますが、_foobarメソッドを使用していませんでした

+0

私は2つのモジュールから継承していないので、実際には問題ではありません。 しかし、私が拡張しているモジュールは私のものではありません(私は作者ではありません)ので、私のサブクラスのアクセサを作成するためにMooseを使用することは何の役にも立たないでしょう。 しかし、おかげで提案。 –

+2

注意してください。 'Moose'以外の' Moose'クラスをサブクラス化することができます。私は 'MooseX :: Declare'にバニラムースを提案します。はるかに良いです。 –

+0

私が意味していたことは、クラスFoo :: Barを作成していて、データの一部にアクセサを実装していないクラスFooを作成しなかったことです。私は作者と連絡を取って、なぜ彼は私がそのデータを突き刺さないようにしているのかを確かめます...しかし、moosexのヒントのおかげで! –

関連する問題