重複の可能性:
インターフェースに Extra メソッドを追加する
Interface X
何千ものクラスで実装されているシナリオがあります。今、その中に新しいメソッドを追加したいと思いInterface X
ます。すべてのクラスでメソッドのオーバーライドの問題を解決するために最小限の方法で変更を加える方法
重複の可能性:
インターフェースに Extra メソッドを追加する
Interface X
何千ものクラスで実装されているシナリオがあります。今、その中に新しいメソッドを追加したいと思いInterface X
ます。すべてのクラスでメソッドのオーバーライドの問題を解決するために最小限の方法で変更を加える方法
追加のメソッドを必要とするクラスに対してのみ、インターフェースの拡張を作成します...
public interface BaseInterface {
public int exampleMethod();
}
public interface ExtendedInterface extends BaseInterface {
public int anotherMethod();
}
何千ものクラスがすでに実装されていますBaseInterface
。追加のメソッドが必要なクラスについては、を実装するように変更しますExtendedInterface
。
オブジェクトがBaseInterface[]
配列などのコレクションに格納されている場合でも、型のExtendedInterface
オブジェクトは型のオブジェクトでもあるため、これは機能しますBaseInterface
。したがって、同じ共通のコレクションに格納できます。
たとえば、これはまだ完全に有効です...
BaseInterface[] objects = new BaseInterface[2];
objects[0] = new ClassThatImplementsBaseInterface();
objects[1] = new ClassThatImplementsExtendedInterface();
ただし、の新しいメソッドにアクセスする必要があるExtendedInterface
が、オブジェクトがBaseInterface
コレクションに保存されている場合は、使用する前にオブジェクトをにキャストする必要がありますExtendedInterface
...
BaseInterface[] objects = new BaseInterface[1];
objects[0] = new ClassThatImplementsExtendedInterface();
if (objects[0] instanceof ExtendedInterface){
// it is an ExtendedInterface, so we can call the method after we cast it
((ExtendedInterface)objects[0]).anotherMethod();
}
else {
// it is a BaseInterface, and not an ExtendedInterface
}
これは、使用法に応じて、適切な場合と適切でない場合があります。
新しいメソッドを実装するために何千ものオブジェクトすべてが本当に必要な場合は、メソッドをに追加してからBaseInterface
、IDEまたはテキストエディタの機能を使用してすべてのクラスにメソッドを実装する必要があります。たとえば、それらをすべてテキストエディタで開き、find-replaceを実行して各クラスに共通するものを検索し、それを共通コード+新しいメソッドのデフォルトコードに置き換えることができます。かなり迅速で痛みがありません。一部のIDEは、おそらくすべての継承クラスにメソッド宣言を自動的に追加するか、少なくとも右クリックメニューでこれを行うオプションがあると確信しています。
新しいメソッドがインターフェイスの真の拡張である場合は、インターフェイスを編集し、開発環境のツールを使用して、新しい機能を実装する必要があるすべての場所を見つけるのが正しい方法です。次に、作業を行います。Eclipse と Netbeans はうまく機能します。
[注意: リファクタリング ツールが手動の作業の一部を処理しないことに少し驚いていますが、そうです。]
新しいメソッドが古いコードでほとんど呼び出されない場合は、新しいインターフェイスが古いインターフェイスの拡張であると考えてください。
public interface NewInterface extends OldInterface {
void newMethod();
}
の null バージョンを使用して、古いインターフェイス オブジェクトを新しいインターフェイス コンシューマに渡す必要がある場合はnewMethod()
、次のようにすることができます。
public class NewInterfaceWrapper<T extends OldInterface> implements NewInterface {
private T wrapped;
public NewInterfaceWrapper(T wrapped) {
this.wrapped = wrapped;
}
// Define all the old interface methods and delegate to wrapped.method
// Now provide the null implementation of new method.
void newMethod() { }
}
...
wantsNewInterface(new NewInterfaceWrapper(oldImplementer));
きれいではありませんが、大きなシステムは通常、年月を重ねるにつれてこのように荒いエッジになります。
これを行う簡単な方法はありません。インターフェイスにメソッドを追加する場合、すべての実装クラスはそれをオーバーライドする必要があります。インターフェイスを抽象クラスに変更する場合は、実装クラスもリファクタリングする必要があります。
しかし、クラス階層がありますよね?したがって、そのメソッドを基本クラスにのみ実装することで、作業を最小限に抑えることができます。ただし、それは特定の要件と詳細に依存するため、実装してよかったと思います!
また、そのような新しいメソッドを実装するために使用できる簡単なクラス階層がない場合は、将来の保守作業を削減するために大幅な書き直しを検討する時期かもしれません。