2009-07-22 4 views
3

複数継承は素晴らしいですし、継承階層といくつかの落とし穴(例えばperldoc perltootに記載されている落とし穴)を明確に理解している限り、Perlはそれをうまく処理します。しかし、複数の継承を持つプラグマfieldsを使用することの禁止については言及していません。確かに、私は全くこのことについて何のドキュメントを見つけることができません...ここでなぜフィールドプラグマはPerlで複数の継承と互換性がありませんか?

はイラストです:

package Parent1; 
use fields 'field1'; 

package Parent2; 
use fields 'field2'; 

package Child; 
use base qw(Parent1 Parent2); 

これはエラーで失敗します。

「で...フィールドを継承し掛けることができません」彼らは共有祖父母から来たので、彼らは、証明可能同じである場合これはさえ ...両方の親が同じフィールドを持っている場合でも動作しません:

package Grandparent; 
use fields qw(field1); 

package Parent1; 
use base 'Grandparent'; 

package Parent2; 
use base 'Grandparent'; 

package Child; 
use base qw(Parent1 Parent2); 

これを正しく実装するうえでの欠点は、子オブジェクト内のフィールドのインデックスが常にその親のインデックスと同じであるという不変条件です。しかし、この要件が本当に必要なのか分かりません... C++とは異なり、親に型付けされたポインタを使ってオブジェクトにアクセスすることができますが、Perlは参照で操作するときにオブジェクトの実際の型を常に知っていますフィールド擬似ハッシュは本質的にvtableであり、単一のオブジェクトインスタンスごとに保持されます)。上記の2番目の例では、特に、各親から継承されたフィールドはの両方ともの親から来ているので、それらは一緒に折り畳むことができ、矛盾するインデックスはありません。

他にも問題があると確信していますが、まだ見つかりませんでした。

これについてPerlの内部についての知識がある人は誰でもコメントできますか?

+0

あなたは2つの親を持つことはできませんし、 'fields'を使って、CPAN –

+0

で他のパッケージを見つけなければなりません。ありがとうございました。 – Ether

+0

@Ether - なぜ受け入れられない答えですか? Thx :) – DVK

答えて

4

1)継承の代わりに委任を使用することができます(as described here)。

2)また、いくつかのドキュメント(上のリンクを含む)は、多重継承の問題が擬似ハッシュのためであることを暗示しているようです。 Perl 5.10は "フィールド"プラグマの実装を擬似ハッシュ以外のものに変更しました。オプションであれば、Perl5.10で使っていたアプローチを試してみてください。それはうまくいくかもしれません(私は5.10へのアクセス権がないので、ごめんなさい)

PS "これについては何も書かれていません"ということについては、少なくとも公式のドキュメントでは、Camelの書籍( "Programming Perl"、O'ReillyのPerlシリーズ)の第3版の章31.3。 "use base":

"Multiple inheritance of field classes is not supported. The use base pragma raises an exception if more than one named base class has fields."

+1

これはperl 5.10でも動作しません。 –

3

フィールドプラグマは興味深い実験でしたが、私の意見では失敗しました。これは、属性ハッシュキーのコンパイル時間チェックの最も便利な機能ですが、5.10で削除されました。 CPANには多くのまともなクラス構成モジュールがありますが、ヘビーウェイトだが着実に普及しているのはMoose( "Perl 5のポストモダンオブジェクトシステム")です。

つまり、複数の継承サポートを追加する場合は、おそらく歓迎されます。フィールドは現在"base" distributionの一部としてperlから独立して管理されていることに注意してください。ただし、擬似ハッシュベース(5.9.0より前)と制限付きハッシュベース(5.9.0 +)の両方の実装で動作させる必要があります。

関連する問題