Java で単一継承をごまかして多重継承を実装する方法があると聞きました。これを実装する方法を知っている人はいますか(インターフェイスを使用せずに)?
単なる好奇心から ;-)
Java で単一継承をごまかして多重継承を実装する方法があると聞きました。これを実装する方法を知っている人はいますか(インターフェイスを使用せずに)?
単なる好奇心から ;-)
確かに可能ですが、それはトリッキーであり、それがあなたが行きたい方法であるかどうかを本当に検討する必要があります。
アイデアは、スコープベースの継承をタイプベースの継承と組み合わせて使用することです。これは、内部目的のために、内部クラスが外部クラスのメソッドとフィールドを「継承」すると言うためのタイプトークです。これは、外部クラスが内部クラスに混合されるミックスインに少し似ていますが、外部クラスの状態を変更したり、そのメソッドを使用したりできるため、それほど安全ではありません。
Gilad Bracha(主要なJava言語デザイナーの1人)が論文を書きましたそれについて話し合う。したがって、いくつかの無関係なクラス間で内部使用するためのいくつかのメソッドを共有したいとします(たとえば、文字列操作のために)、必要なすべてのメソッドを持つクラスの内部クラスとしてそれらのサブクラスを作成でき、サブクラスはスーパークラスと外部クラスの両方からのメソッド。
とにかく、それは複雑なクラスには注意が必要であり、静的インポート(Java 5以降)を使用してほとんどの機能を取得できます。就職の面接やパブクイズには素晴らしい質問ですが;-)
単一の複数の継承は Java ではサポートされていません。代わりに、同じ目的を果たすためのインターフェイスがあります。多重継承の使用に固執する場合は、C++ で行う必要があります。
継承の代わりに構成を使用することは、これを回避する方法になる傾向があります。これは実際にはテスト容易性にも大いに役立つため、一般的には良い習慣です。
ただし、自分の型を他のいくつかの型のように "動作" させたい場合は、好きなだけインターフェイスを継承できます。ただし、明らかに、これらから実装の詳細を「借りる」ことはできません。
Java が多重継承をサポートしない根本的な理由は、C# と同じだと思います。すべてのオブジェクトは最終的に Object から派生し、同じ基本クラスへの複数のパスを持つことは、コンパイラにとってあいまいです。あいまいな == 悪いので、コンパイラはそれを許可しません。
代わりに、委任によって多重継承をシミュレートできます。例については、この記事を参照してください。
java.lang.reflect.Proxy インスタンスを使用すると、少しごまかすことができます (私は少し強調します)。
これにより、実際には、追加のインターフェイスを追加し、実行時にそれらの呼び出しを別のインスタンスに委任することができます。
新しい開発者を指導し指導する者として、誰かがこれを行うコードを私に見せたら、ぞっとするでしょう。リフレクションは、Java に飛び込む前に、本当に理解し、十分に理解する必要があるツールの 1 つです。私は個人的にこれを行ったことが一度だけあります。私が制御できなかった他のコードは予想通りでした (簡単なハックだったので、あまり多くのグルー コードを作成して維持する必要はありませんでした)。
スーパークラスのセットを明示的に管理し、リフレクションを使用してターゲット メソッドのすべてのスーパークラスを検索することで、おそらく「シミュレート」できます。これは本番環境ではやりたくありませんが、面白いおもちゃのプログラムになるかもしれません。リフレクションを利用したり、オンザフライでクラスを作成したり、プログラムでコンパイラを呼び出したりすることで、おそらく多くの奇妙なことを実行できます。
sを使用interface
します。いくつでも実装できます。通常、必要に応じて、複合パターン (GoF)でいくつかのバリアントを使用して、実装コードを再利用できます。
インターフェイスの継承 (本質的には、特定の機能を提供するためのコントラクトの継承) と実装の継承 (実装メカニズムの継承) を区別するように注意する必要があります。
Java は実装メカニズムによるインターフェース継承を提供し、複数のインターフェース継承を持つことができます。
実装の継承は拡張メカニズムであり、そのバージョンは 1 つしかありません。複数の実装継承が本当に必要ですか? とにかくあなたが Eiffel プログラマでない限り、不快な結果がぎっしり詰まっています。
内部クラスを使用することで、これは C++ が好むこともあります: Inner Class Idiom .
JAVA は複数の継承をサポートしていません。
複数のインターフェースを実装することができ、これを問題を回避する方法と見なす人もいます。個人的にはまだ多重継承を使ったことがないので、その魅力がよくわかりません。
通常、誰かが c# または JAVA 内で多重継承を提案する場合、それは c++ で「できる」という事実によるものです。私は「できるからといって、すべきだとは限らない」のファンです。c# と JAVA はそれをサポートしていないので、設計されていないことを強制しようとするのはなぜですか。これは、使用する有効な手法であるという特殊なケースがあると言っているわけではなく、通常はコードをリファクタリングして不要にすることができます。
ミックスインを Java に導入する取り組みがありました。このリンクをチェックしてください: http://www.disi.unige.it/person/LagorioG/jam/
私はこれについてもう少し考えていて、動的プロキシは機能しますが(RMI(使用?)が機能する方法です)、この種の機能が本当に必要な場合は、アスペクト指向プログラミング(AOP) AspectJ (eclipse.org/aspectj) のようなものです。
このようにして、非常に壊れやすい継承階層なしで、疑似 mixin 継承を提供して、いくつかの異なる側面をクラスに取り込むことができます。
他の誰もが指摘しているように、多重継承が必要な場合は、通常、正しい観点から問題に取り組んでいないことを示しています。まず、「継承よりも構成を優先する」という GoF の原則を思い出してください。