2

Javaでは、新しいメソッドをインターフェースに追加すると、すべてのクライアントが壊れます。抽象クラスがある場合は、新しいメソッドを追加して、その中にデフォルトの実装を提供できます。すべてのクライアントは引き続き機能します。

なぜインターフェースがこのように設計されているのだろうか?

古いメソッドはすべてまだ存在しているため、下位互換性の問題はないようです。(もちろん、特定の例外が必要ですが、クライアントを壊さずにJavaインターフェイスに新しいメソッドを追加できるようにすることは本当に良い考えだと思います...)

コメントありがとうございます。

4

4 に答える 4

3

私が見ることができるいくつかの可能な休憩があります

  • クライアントが新しいオーバーロードされたメソッドを使用すると想定しますが、コードが再コンパイルされていないため、クライアントは使用しません。
  • クライアントがすでに持っていたメソッドを追加して、何か違うことをします。
  • 再コンパイル時にサブクラスが壊れることを意味するメソッドを追加します。私見 これは望ましいことです。
  • 戻り値の型、メソッド名、またはパラメーターの型を変更すると、実行時にエラーが発生します。
  • 同じタイプのパラメーターを交換します。これはおそらく最悪で最も微妙なバグです。;)

私見、あなたを悲しませる可能性が高いのは微妙な問題です. ただし、単純にメソッドを追加するだけでコードが壊れるとは思いませんし、クライアントのコードで実行時エラーが発生していないからといって、最新バージョンを使用しているとは限りません。;)


このコードをコンパイルすると

public interface MyInterface {
    void method1();

    // void method2();
}

public class Main implements MyInterface {
    @Override
    public void method1() {
        System.out.println("method1 called");
    }

    public static void main(String... args) {
        new Main().method1();
    }
}

それは印刷します

method1 called

次に、method2() のコメントを外し、インターフェイスだけを再コンパイルします。これは、インターフェイスにMain実装されていないメソッドがあることを意味します。それでも、再コンパイルせずに実行するMainと、

method1 called

私が持っている場合

public class Main implements MyInterface {    
    public void method1() {
        System.out.println("method1 called");
    }

    public void method2() {
        System.out.println("method2 called");
    }

    public static void main(String... args) {
        new Main().method1();
    }
}

// method2()コメントアウトして実行しますが、問題はありません。

于 2012-09-24T08:51:43.153 に答える
1

インターフェイスは、クラスのテンプレートのようなものです。クラスが特定のインターフェースを実装するオブジェクトがあり、そのインターフェースにキャストすると、そのインターフェースを介してのみそのオブジェクト (およびそのメソッド) にアクセスできます。したがって、クライアントは、クラスによって実際に実装されているメソッドだけでなく、インターフェイスによって提供されるすべてのメソッドを常に見ることができます。

あなたの提案は、あなたが今処理しているオブジェクトが、呼び出しようとしているメソッドの実装を実際に持っているかどうか疑問に思う結果になるでしょう。

もちろん、レガシークライアントでは発生しないシナリオでは、いつかそれらを更新し、IDE がプレビューするすべてのメソッドの実装を持つオブジェクトに依存するまでは。:)

抽象クラスの事実は(まさにあなたが述べたように)デフォルトの実装を提供するため、クライアント側ではメソッドが実装されたオブジェクトに依存できるということです。

これが問題を解決するのに役立つことを願っています。

よろしく

于 2012-09-24T08:48:50.670 に答える
0

インターフェイスは、そのインターフェイスからそのユーザーが使用できるすべてのメソッドのセットを表し、他のメソッドを追加できるメソッドの一部ではありません。それは、それ以下でもそれ以上でもないという契約です。

このデザインの良いところは、あいまいさがないことです。Java は静的に型付けされた言語であり、Interface宣言から利用可能なすべてのメソッドを完全に把握する必要があります。JVM 内にはInterface クラスの表現が 1 つしかなく、利用可能な抽象メソッドの完全なセットを含める必要があります。

いくつかの実装されたメソッドを持つ抽象クラスがある場合、インスタンス化することはできませんが、その唯一の目的は拡張され、その抽象メソッドが実装されるクラスであるというセマンティクスです。抽象クラスは IS-A 関係を強制しますが、インターフェースは BEHAVES-AS を強制します

于 2012-09-24T08:57:12.480 に答える
0

インターフェイスの役割は、メソッドの宣言だけではありません。それらは、契約ベース/最初の開発のまさに基礎を形成します。これらのコントラクト api は、入力となるものと出力となるものを定義します。また、契約と同様に、すべての条件が満たされた場合にのみ有効です。これが、クラスが実装されたインターフェースのすべての API を実装することが必須である理由です。

バージョンと新しい開発を処理する方法を定義する設計パターンがあります。これらのインターフェイスの実装をインスタンス化するときに使用する必要があるファクトリ/抽象ファクトリ パターン (適切なバージョンが使用される実装であることを内部的に検証できるようにするため)。

あなたが求めている柔軟性は、プログラミング言語に期待するのではなく、適切な設計によって実装できます。プログラミング ツールの場合、新しいバージョンの実装を古いインターフェイスにプラグインすることはプログラミング エラーです。しかし、下位互換性の中断とは異なります。コンポーネントの新しいバージョンが利用可能になったからといって、下位互換性が失われるとは限りません。成熟した製品またはコンポーネントは、メンテナンスが本当に面倒にならない限り、常に古いバージョンをサポートします。したがって、ほとんどの場合、利用したい新機能がない限り、ユーザーは新しいバージョンが利用可能かどうかを心配する必要はありません。

于 2012-09-24T09:04:52.327 に答える