インターフェイスの一部のみを実装する方法


14

OOPで開発する場合、変更できないライブラリによってインターフェイス/コントラクトが与えられることがあります。このインターフェイスをJと呼びましょう。

これで、このインターフェイスを実装するオブジェクトを消費するクラスAのオブジェクトができました。Inside Aインターフェイスの定義のほんの一部だけが必要です。オブジェクトクラスの一部はプロジェクト中に私が作成します(そのうちの1つをタイプDと呼びましょう)。したがって、インターフェイスJ内のすべての実装にオーバーヘッドがあります。

インターフェイスJの機能のサブセットを実装したいのですが、これまでのソリューションでは満足できません。

  • Jのあらゆる側面を実装し、「notImplementedExceptions」をスローすると、ユーザーにオブジェクトの情報が誤って通知されます。タイプDのオブジェクトはインターフェースJに準拠しているように見えますが、 J)オブジェクトの整合性に依存することはできません。
  • 新しく定義されたインターフェイスを実装すると、インターフェイスJのみを実装するオブジェクトを使用できなくなりますが、インターフェイスJは自分のインターフェイスと完全に互換性があります。
  • カスタムオブジェクトにインターフェイスJを実装させると、この機能をすべて必要としないため、かなりのオーバーヘッドが発生します。

インターフェースJを変更できた場合、インターフェースJの機能のこのサブセットを持つ「スーパーインターフェース」Kを作成し、インターフェースJをインターフェースKから継承させます。しかし、インターフェースJを変更することはできません。

この問題のオブジェクト指向ソリューションとは何ですか?最良のソリューションは、まだ「単なる」インターフェースJを実装していますか?または、インターフェイスを変更せずに「スーパークラス化」するOOPの方法はありますか?


1
Swingの* Adapterクラスがこれを行う方法を参照してください。

回答:


9

インターフェイスJを制御しないと、行き詰まってしまいます。

明確にするために、独自のインターフェイスsubJ インターフェイスJを実装し、独自のコードでsubJを使用して、インターフェイスJの追加のメソッドが不要であることを明確にすることができますが、それは本当にあなたを得るとは思いません

可能であれば、インターフェイスJ全体を完全に実装します

可能であれば、インターフェイスJの所有者に連絡し、目的に合わせて変更するよう依頼してください。


2
妥協案として、インターフェイスJの所有者に、より小さいインターフェイスSubJから継承するように依頼できます。
k3b

27

インターフェイスを実装する全体のポイントは、呼び出し元と呼び出し先の間で、実装の詳細が変化しても変わらない堅実な契約を提供することです。

インターフェースJを実装することにより、外の世界に何ができるかを伝えます。

Jの半分を必要としない場合は、インターフェースを可能な限り小さくしないために実際に細分化するか、NotImplementedException不要なメソッドとプロパティを使用する必要があります。しかし、これは最良の解決策ではありません。コードができることに対する人々の期待を混乱させるからです。


5

コンシューマクラスAがすべてのインターフェイスJを必要としない場合は、必要なすべてを包括的に記述する新しいインターフェイス(Kと呼ぶ)を作成することをお勧めします。

これにより、クラスAを使用している人に、契約の側について明確なシグナルが提供されます。これにより、再利用の可能性が向上します。比較的単純なことを行うために、誰かが大きく複雑なインターフェースを実装するオブジェクトを提供する必要がある場合、クラスA自身が行うことは何でも書くことになります。

クラスAがインターフェイスJのみを実装するオブジェクトを消費できるようにするには、インターフェイスKを実装し、インターフェイスJメンバーに適切な呼び出しを渡すラッパークラスを提供できます。


3

Jを完全に実装する必要がある(実装されていないメソッドを除く)か、まったく実装する必要がないという既存の回答に同意しますが、考えられる回避策は次のとおりです。

  • Jのサブセットであり、必要なメソッドを実装する小さなインターフェイスKを作成します。
  • JおよびKを実装するオブジェクトを受け入れるAのラッパーを作成します。
  • Jで渡された場合、単純にAのインスタンスにプッシュします。
  • Kで渡された場合、Jの匿名実装をインスタンス化し、そこにあるKからJへのメソッドのみをワイヤリングします。結果をAのインスタンスに渡します。

これは本質的に同じものである複数のものを受け入れるラッパーを必要とするため、これは非常にい解決策であることに注意してください。ただし、次のことは実現します。

  • JまたはAに変更はありません。
  • 不完全なJの「公開された」実装はありません。

OO言語で匿名インターフェースのインスタンス化が許可されていない場合は、インターフェースのダミー実装を作成してインスタンス化できます。


1

インターフェイス全体を実装するのにどれくらい時間がかかりますか?

かなりの時間がかかる場合、これは設計上の問題を示していますので、所有者に連絡して、将来変更できるかどうかを確認することをお勧めします。

インターフェイスのライブラリとは無関係に、独自のコードでインターフェイスを使用していますか?

Steven A.が提案したように、独自のコードで見たい場合は、独自のインターフェイスを使用できます。これにより、少なくとも社内コードがクリーンに保たれます。また、これをあなたが見つけると期待されるインターフェースとして所有者に送信することもできます。おそらく彼はあなたに同意するか、インターフェースを分割しない理由を説明できるでしょう。

あなたの実装は、インターフェースの未使用のメンバーを必要としますか?

「サポートされていない」ために呼び出されないことが予想される場合は、を使用することをお勧めしますNotSupportedException。これにより、このインターフェイスを実装しなかったのではなく、決してサポートしないことを明確に示しています。


使用NotSupportedExceptionすることをお勧めすると、その方法をサポートしていないことが明確になります。
ChrisF

@ChrisF:私NotImplementedExceptionは、そうでなければ「TODO:これを実装する」と書くプロダクションコードにのみ使用します悲しいことに、それらはVisual Studioのタスクリストに表示されません。しかし、実際には、メソッドを2日間以上実装しないままにすることはほとんどありません。Resharperは、これらの例外を太字で示しています(少なくとも私の設定では)。:)
スティーブンジュリス

0

必要なものを実装し、他に対して例外NoImplementedExceptionをスローします。

これは使用の問題です。インターフェイスを使用しない場合、またはコードがインターフェイスを使用しないことがわかっている場合は、冗長なコードに時間を投資する必要がないため、これに時間を費やさないでください。

手元のタスクに取り組み、他のユーザーがインターフェイスを使用したい場合にフォローするための良い道を保ちます。

Javaの多くのインターフェースは完全には実装されていません。

これは物事に対するApacheのアプローチです:http ://commons.apache.org/lang/api-2.4/org/apache/commons/lang/NotImplementedException.html


おそらくこれが適切な解決策であるとあなたが信じる理由を議論するでしょう。これは質問に何も追加しません。
スティーブンジュリス

すべてを説明する実際の必要がないので、すべてを実装する必要はありません。それが彼の場合、インターフェースの一部は冗長であり、彼はすぐにそれを拾いました。
表示名
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.