91

2 つのインターフェイスがあり、どちらも目的がまったく異なりますが、同じメソッド シグネチャを使用している場合、両方のインターフェイスに対応する単一のメソッドを強制的に記述したり、メソッドに複雑なロジックを記述したりすることなく、クラスに両方を実装するにはどうすればよいですか呼び出しが行われているオブジェクトのタイプをチェックし、適切なコードを呼び出す実装ですか?

C# では、これは明示的なインターフェイスの実装と呼ばれるものによって克服されます。Java に同等の方法はありますか?

4

7 に答える 7

77

いいえ、Java の 1 つのクラスで同じメソッドを 2 つの異なる方法で実装する方法はありません。

これは多くの混乱を招く状況につながる可能性があるため、Java はこれを許可していません。

interface ISomething {
    void doSomething();
}

interface ISomething2 {
    void doSomething();
}

class Impl implements ISomething, ISomething2 {
   void doSomething() {} // There can only be one implementation of this method.
}

できることは、それぞれが異なるインターフェースを実装する 2 つのクラスからクラスを構成することです。次に、その 1 つのクラスが両方のインターフェイスの動作を持ちます。

class CompositeClass {
    ISomething class1;
    ISomething2 class2;
    void doSomething1(){class1.doSomething();}
    void doSomething2(){class2.doSomething();}
}
于 2010-04-08T06:38:36.067 に答える
14

Java でこれを解決する実際の方法はありません。回避策として内部クラスを使用できます。

interface Alfa { void m(); }
interface Beta { void m(); }
class AlfaBeta implements Alfa {
    private int value;
    public void m() { ++value; } // Alfa.m()
    public Beta asBeta() {
        return new Beta(){
            public void m() { --value; } // Beta.m()
        };
    }
}

AlfaBetaからへのキャストは許可されていませんが、ダウンキャストは一般的に悪であり、インスタンスにもアスペクトがあるBetaことが予想される場合、何らかの理由で (通常は最適化が唯一の正当な理由です)、できるようにしたいと考えています。に変換するには、その中に のサブインターフェイスを作成できます。AlfaBetaBetaAlfaBeta asBeta()

于 2010-04-08T14:03:04.273 に答える
12

この問題が発生した場合は、delegationを使用する必要がある場所で継承を使用している可能性があります。同じ基になるデータ モデルに対して 2 つの異なる (類似ではあるが) インターフェースを提供する必要がある場合は、ビューを使用して、他のインターフェースを使用してデータへのアクセスを低コストで提供する必要があります。

後者の場合の具体的な例を示すために、(継承せず、互換性のないインターフェースを持つ) と の両方Collectionを実装するとします。同じ基本データを使用して、およびの軽量実装を提供するおよび関数を提供できます。MyCollectionCollectionCollection getCollectionView()MyCollection getMyCollectionView()CollectionMyCollection

前者の場合...整数の配列と文字列の配列が本当に必要だとします。List<Integer>との両方から継承する代わりにList<String>、 type の 1 つのメンバーと typeList<Integer>の別のメンバーを持ちList<String>、両方から継承しようとするのではなく、それらのメンバーを参照する必要があります。整数のリストのみが必要な場合でも、この場合は継承よりも構成/委任を使用することをお勧めします。

于 2010-04-08T06:39:42.750 に答える
1

「古典的な」Java の問題は、私の Android 開発にも影響します...
理由は単純なようです
。使用する必要があるフレームワーク/ライブラリが増えると、制御不能になりやすくなります...

私の場合、BootStrapperAppクラスがありますandroid.app.Applicationから継承されますが、同じクラスは、統合するために MVVM フレームワークのプラットフォーム
インターフェイス も実装する必要があります。getString()メソッドで メソッド衝突が発生しました。これは、両方のインターフェースによってアナウンスされ、異なるコンテキストで異なる実装を持つ必要があります。 回避策(醜い..IMO)は、内部クラスを使用してすべてのプラットフォームを実装しています

メソッドのシグネチャの競合が 1 つあるだけで...場合によっては、そのような借用したメソッドがまったく使用されないことさえあります (ただし、主要な設計セマンティクスに影響を与えます)。
私は、C# スタイルの明示的なコンテキスト/名前空間の表示が役立つことに同意する傾向があります。

于 2013-03-29T10:01:10.730 に答える
1

私の頭に浮かんだ唯一の解決策は、複数のインターフェースを実装したいオブジェクトへの参照オブジェクトを使用することです。

例: 実装するインターフェースが 2 つあるとします。

public interface Framework1Interface {

    void method(Object o);
}

public interface Framework2Interface {
    void method(Object o);
}

それらを 2 つの Facador オブジェクトに含めることができます。

public class Facador1 implements Framework1Interface {

    private final ObjectToUse reference;

    public static Framework1Interface Create(ObjectToUse ref) {
        return new Facador1(ref);
    }

    private Facador1(ObjectToUse refObject) {
        this.reference = refObject;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Framework1Interface) {
            return this == obj;
        } else if (obj instanceof ObjectToUse) {
            return reference == obj;
        }
        return super.equals(obj);
    }

    @Override
    public void method(Object o) {
        reference.methodForFrameWork1(o);
    }
}

public class Facador2 implements Framework2Interface {

    private final ObjectToUse reference;

    public static Framework2Interface Create(ObjectToUse ref) {
        return new Facador2(ref);
    }

    private Facador2(ObjectToUse refObject) {
        this.reference = refObject;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Framework2Interface) {
            return this == obj;
        } else if (obj instanceof ObjectToUse) {
            return reference == obj;
        }
        return super.equals(obj);
    }

    @Override
    public void method(Object o) {
        reference.methodForFrameWork2(o);
    }
}

最後に、必要なクラスは次のようになります

public class ObjectToUse {

    private Framework1Interface facFramework1Interface;
    private Framework2Interface facFramework2Interface;

    public ObjectToUse() {
    }

    public Framework1Interface getAsFramework1Interface() {
        if (facFramework1Interface == null) {
            facFramework1Interface = Facador1.Create(this);
        }
        return facFramework1Interface;
    }

    public Framework2Interface getAsFramework2Interface() {
        if (facFramework2Interface == null) {
            facFramework2Interface = Facador2.Create(this);
        }
        return facFramework2Interface;
    }

    public void methodForFrameWork1(Object o) {
    }

    public void methodForFrameWork2(Object o) {
    }
}

getAs* メソッドを使用してクラスを「公開」できるようになりました

于 2013-05-21T17:41:15.370 に答える
0

これらを機能させるためにアダプターパターンを使用できます。インターフェースごとに 2 つのアダプターを作成し、それを使用します。それは問題を解決するはずです。

于 2014-12-01T21:39:44.763 に答える