web-dev-qa-db-ja.com

javaでの複数の汎用インターフェースの実装

特定の署名を含む特定のメソッドが利用可能であることを保証するインターフェイスが必要です。これまでのところ、彼は私が持っているものです:

public interface Mappable<M> {
    M mapTo(M mappableEntity);
}

この問題は、クラスを他の複数のエンティティにマップできる場合に発生します。理想的なケースはこれです(Javaではありません)。

public class Something implements Mappable<A>, Mappable<B> {
    public A mapTo(A someObject) {...}
    public B mapTo(B someOtherObject) {...}
}

これを可能な限り「一般的な」ものにするための最良の方法は何でしょうか?

10
estani

もちろん、これは Type Erasure のためにできることではありません。実行時には、2つのメソッドpublic Object mapTo(Object)が存在しますが、これらは明らかに共存できません。

残念ながら、あなたがやろうとしていることは、Javaの型システムを超えているだけです。

ジェネリック型が常に最初のクラス型であり、それ自体がジェネリックではないと想定すると、メソッドmapTo(Object, Class)を使用することで、同様の外向きの動作を実現できます。これにより、特定のクラスのランタイム検査を実行して決定できます。使用する動作。明らかにこれはかなり洗練されておらず、戻り値を手動でキャストする必要がありますが、私はそれがあなたができる最善の方法だと思います。ジェネリック型自体がジェネリックである場合、ジェネリックパラメーターも消去され、クラスが等しいため、このメソッドは機能しません。

ただし、@ Joachimの回答も指摘しておきます。これは、動作を個別のコンポーネントに分割して、問題全体を回避できる場合です。

10
Phoshi

ご覧のように、異なる型パラメーターを使用して同じインターフェイスを2回実装することはできません(消去のため:実行時は同じインターフェイスです)。

また、このアプローチは単一の責任の原則に違反します。クラスはSomething(意味が何であれ)であることを重視し、AまたはBへのマッピングを行うべきではありません- さらにそのタスク。

あなたは本当にMapper<Something,A>Mapper<Something,B>。このようにして、各クラスには明確に定義された単一の責任がありますand同じインターフェースを2回実装する問題に遭遇しません。

3
Joachim Sauer

複数のインターフェイスを実装することが許可されていない場合は、カプセル化の使用を検討できます。 (Java8 +を使用した例)

// Mappable.Java
public interface Mappable<M> {
    M mapTo(M mappableEntity);
}

// TwoMappables.Java
public interface TwoMappables {
    default Mappable<A> mapableA() {
         return new MappableA();
    }

    default Mappable<B> mapableB() {
         return new MappableB();
    }

    class MappableA implements Mappable<A> {}
    class MappableB implements Mappable<B> {}
}

// Something.Java
public class Something implements TwoMappables {
    // ... business logic ...
    mapableA().mapTo(A);
    mapableB().mapTo(B);
}

詳細と例については、こちらをご覧ください。 Java 2つのジェネリック型の1つのインターフェースを実装するクラスを作成する方法 の作成方法。

0
winter