4

多くの質問で述べられているように、同じメソッドを持つ2つのインターフェースを1つのクラスで継承することはできないといつも思っていました。

Java jre 7、jdk 1.7

しかし、ここのこのコードは機能しています。

例:

インターフェース:

public interface IObject
{
    public Object create(Object object) throws ExceptionInherit;
}

public interface IGeneric<T>
{
    public T create(T t) throws ExceptionSuper;
}

クラスの実装:

public class Test implements IGeneric<Object>, IObject
{
    @Override
    public Object create(final Object object) throws ExceptionInherit
    {
        return object;
    }
}

これらの2つのメソッド宣言は同じ本体を持っていませんか?

例外:

例外は、この構成に追加するだけであり、より複雑になります。

public class ExceptionSuper extends Exception {}
public class ExceptionInherit extends ExceptionSuper {}

スローされた例外なしでも機能します。

さらに:両方のメソッドインターフェイスが異なる継承例外をスローする場合UserLogic、2つのインターフェイスのいずれかにキャストして、例外の異なるサブセットを取得できます。

なぜこれが機能しているのですか?

編集:

The generic implementation is not even necessary:

public interface IA
{
    public void print(String arg);
}

public interface IB
{
    public void print(String arg);
}

public class Test implements IA, IB
{
    @Override
    public void print(String arg);
    {
        // print arg
    }
}
4

5 に答える 5

3

これで、UserLogicを2つのインターフェイスのいずれかにキャストして、異なる例外のセットを取得できます。

いいえ、できません。JoshuaBlochとNealGafterによる「JavaPuzzlers:Traps、Pitfalls、and Corner Cases」、Puzzle 37ExceptionallyArcaneを参照してください。

各インターフェイスは、メソッドがスローできるチェック済み例外のセットを制限します。メソッドがスローできるチェック済み例外のセットは、ユニオンではなく、該当するすべてのタイプでスローするように宣言されているチェック済み例外のセットの共通部分です。

したがって、あなたの場合の実装

create(ユーザーユーザー)はExceptionInheritをスローします

正しい。だが

create(ユーザーユーザー)はExceptionSuperをスローします

コンパイルされません

于 2012-10-06T14:24:38.163 に答える
2

ExceptionInheritextendsを使用するため、別の例外を受け取ることはありませんExceptionSuper。しかし、これを考慮してください:

interface X {
    public void foo() throws ExceptionA;
}

interface Y {
    public void foo() throws ExceptionB;
}

class ExceptionA extends Exception {}
class ExceptionB extends Exception {}

class Z implements X, Y {
    public void foo() throws ExceptionA {

    }
}

継承によって接続されていないことに注意しExceptionAてください。ExceptionBこの場合、の句とExceptionA互換性がないため、コンパイルエラーが発生します。throwsY

于 2012-10-06T14:18:58.693 に答える
1

例外なく、ジェネリックなしでも機能します。Java 1.4までさかのぼり、おそらく以前もそうです。

多くの質問で述べられているように、同じメソッドを持つ2つのインターフェースを1つのクラスで継承することはできないといつも思っていました。

これは実際には真実ではなく、あなたがどの質問を参照しているのかわかりません。

もちろん、同じメソッドシグネチャを持つ2つのインターフェイスを使用しない理由はあります。最も重要な理由は、実装が1つのことしか実行できないため、両方のインターフェイスがメソッドから異なる結果を期待する場合、両方のインターフェイスを満たすことはできません。 、ただし、これはコンパイルエラーにはなりません。

同じメソッドで2つのインターフェースを持つことが完全に有効である理由もあります。2つのインターフェースが相互に拡張する場合、実装は両方のインターフェースを適切に実装できます。インターフェイスが名前を共有するだけの単純な状況でも、技術的な制限はありません。

インターフェイスは、特定のメソッドが使用可能であることを要求するだけであり、他のインターフェイスが存在しないことを要求しません。

有効なコード:

public interface IDo {
    public void does();
}


public interface ITwo {
    public void does();
}

public class Test implements IDo, ITwo {
public void does() {
}
}
于 2012-10-06T15:12:41.620 に答える
1
I always thought that two interfaces with the same method cannot 
be inherited by one class, as stated in many so questions.

より正確にしたい場合は、「同じメソッド」を「オーバーライドと同等のシグネチャを持つメソッド」に置き換える必要があります。シグニチャは「メソッド名」+「パラメータリスト」です(一部のルールはreturntypeとthrows句にも適用されます)。オーバーライドと同等の意味を正確に知る必要があります。

次の条件を満たせば、クラスがそのようなメソッドを使用して2つ以上のインターフェイスを実装する場合はまったく問題ありません。

1-それらすべてが同じリターンタイプを持っているか、それらのメソッドの1つが他のすべてのサブタイプであるリターンタイプを持っています。これは、実装で使用する必要がある戻りタイプです。

例えば:

interface A {
    Integer x();
}

interface B {
    Number x();
}

interface C {
    Object x();
}

class Foo implements A, B, C
{
    Integer x() { 
        //...
    }
}

2-実装は、各スーパーインターフェイスが宣言したすべてのそのようなメソッドのthrows句を満たす必要があります。

したがって、あなたが与えた例はこれらの規則に準拠しており、完全に問題ありません。

于 2012-10-06T17:12:01.327 に答える
0

同じ署名のメソッドを持つ2つのインターフェースを確実に「実装」できます。同じメソッド実装を持つ2つのクラスを「拡張」しようとすると問題が発生します。複数インターフェースの継承は良好です。複数実装の継承はTRICKYです。

「ExceptionSuper」オブジェクトは継承するため、「ExceptionSuper」オブジェクトの代わりに「ExceptionInherit」オブジェクトを使用できます。「ExceptionInherit」オブジェクトには、「ExceptionSuper」オブジェクトが行うすべての情報(およびその他)が含まれています。これは逆ではありません。「ExceptionInherit」コードはベースオブジェクトが持っている以上のものを期待しているため、「ExceptionInherit」オブジェクトの代わりに「ExceptionSuper」オブジェクトを使用することはできません(場合によってはそうではありません)。

「create」メソッドの実装は、「ExceptionInherit」と「ExceptionSuper」の両方のキャッチャーにスローできる「ExceptionInherit」をスローするため、ICreateUserの「create」シグネチャを埋めます。必要なすべての情報(基本クラスのみ)を取得します。オブジェクト。

「ExceptionInherit」を期待するキャッチャーは十分な情報を持たないオブジェクトを取得するため、「ExceptionSuper」をスローするように実装を変更することはできません。

于 2012-10-06T14:39:38.567 に答える