簡潔な答え:
次の例を検討してください。
最初の例(あなたの例から):
INTERFACE `IFace` (
METHOD `printFibonacci` (INT) : NIL
)
CLASS `A` IMPLEMENTS `IFace` (
METHOD `printFibonacci` (NUMBER n) : NIL (
//what if the number is a not an integer? Can we guarantee to the client that we are respecting the method signature?
)
)
2 番目の例:
public interface Talking {
public void speak(Human human);
}
public class Employee implements Talking {
public void speak(Animal animal) {
// can we speak with a cockroach?
}
}
階層を上っていくということは、スーパータイプがサブタイプの機能と属性を持っていないことを意味するため、インターフェースが尊重されないリスクがあります: param 型を抽象化することが可能であれば、インターフェースを実装するクラスを持つことが可能になります。すべての型が Object から継承されるため、メソッドMETHOD
f(ANY_TYPE) : NIL
をMETHOD
fに再定義します。(OBJECT) : NIL
そのため、数値をMETHOD
fに渡すクラスを定義(INT) : NIL
するだけでなく、文字列を渡す別のクラスを定義することも可能であり、インターフェイスの署名とクライアントとの契約を破る危険があります (以下を参照)。
長い答え:
インターフェイスを実装する主な目的は、それを実装するクラスではなく、そのインターフェイスのみを認識するクライアントに公開することです。このようにして、同じインターフェイスを実装するさまざまなクラスをクライアントに渡し、クライアントを変更せずにソフトウェアの機能を変更できます。
クライアントとのコントラクトは、クラスではなくインターフェイスで指定されます (そのコントラクトは、高レベルのブラック ボックス コンポーネント設計をモデル化します)。
実際、インターフェイスは、クラス メソッドの署名を(ほぼ合法的な方法で)指定し、設計の最も重要な部分である契約による設計の観点から指定します。クラスは、それを公開する必要があるインターフェースの化身です。
したがって、インターフェイスはクラスの抽象データ型の動作を定義しており、クラスがその定義を変更できる場合、署名を変更するクライアントとの「法的」契約を破ることができます。
また、パラメータを抽象化する場合もコントラクトを変更しています。これは、より抽象的なデータ型がより具体的なものとは異なる動作と属性を持つためです。サービスのプロバイダー (クラス) が署名を変更してコントラクトを変更する上記の例を参照してください。署名後に契約が変更された場合、誰も満足しません。
Java ではインターフェースが複数の継承を持つことができるため、これは設計を制限するものではありません。さらに、JDK5 からは、インターフェースでGenericsを使用できます。
したがって、ジェネリックを使用して次のことができます。
public interface IFace<T> {
public void f(T n);
}
サブクラスでは、型に制約はありません。
この場合、コントラクトはパラメーターの型について何も指定していないため、クライアントは何も期待してはならず、私たちを訴えることはできないことに注意してください。