Java에서 여러 일반 인터페이스 구현


10

특정 서명을 포함한 특정 방법을 사용할 수있는 인터페이스가 필요합니다. 지금까지 내가 가진 것은 다음과 같습니다.

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

물론 이것은 Type Erasure 로 인해 할 수있는 일이 아닙니다 . 런타임 public Object mapTo(Object)에는 공존 할 수없는 두 가지 방법 이 있습니다.

불행히도, 당신이하려는 것은 단순히 Java 유형 시스템을 넘어서는 것입니다.

제네릭 형식이 항상 첫 번째 클래스 형식이고 일반 형식이 아니라고 가정하면 메서드를 사용하여 비슷한 바깥 쪽을 향한 동작 mapTo(Object, Class)을 수행 할 수 있습니다. 이렇게하면 지정된 클래스의 런타임 검사를 수행하고 사용할 동작을 결정할 수 있습니다. 분명히 이것은 매우 우아하지 않으며 반환 값을 수동으로 캐스팅해야하지만 최선의 방법이라고 생각합니다. 제네릭 형식이 제네릭이면 제네릭 매개 변수도 지워지고 클래스가 동일하므로이 방법이 작동하지 않습니다.

그러나 @Joachim의 대답을 지적 할 것입니다. 이것은 동작을 분리 된 구성 요소로 나누고 전체 문제를 회피 할 수있는 경우 일 수 있습니다.


3

보시다시피, 다른 유형 매개 변수를 사용하여 동일한 인터페이스를 두 번 구현할 수 없습니다 (지우기 때문에 : 런타임에 인터페이스가 동일 함).

또한이 접근법은 단일 책임 원칙을 위반합니다. 클래스는 Something(그것이 무엇이든간에) 중점을 두어야하며 해당 작업 매핑 A하거나 해당 작업 B 을 추가 해서는 안됩니다 .

당신이 정말로 a Mapper<Something,A>와 a을 가져야 할 것 같습니다 Mapper<Something,B>. 이런 식으로 각 클래스에는 명확하게 정의 된 단일 책임이 있으며 동일한 인터페이스를 두 번 구현하는 문제는 발생하지 않습니다.


글쎄, 아이디어는 클래스가 그 내용을 다른 객체로 "변환"하는 책임을지게하는 것입니다. 그런 다음 클래스와 무관하게 처리하는 디스패처가 있으므로 제네릭 요구 사항이 있습니다. 나는 논리를 추출하는 것에 대해 조금 생각할 것입니다. 실제로 클래스를 두 개로 나눕니다. 그러나 그들은 밀접하게 결합되어 있습니다 (필드에 대한 액세스 권한이 부여되어야하며, 대부분의 시간을 수정해야 다른 시간을 수정하는 등)
estani

@estani : 그렇습니다. 그들은 다소 밀접하게 결합되어 있지만 뚜렷한 책임이 있습니다. 또한 이것에 대해 생각하십시오 : 새로운 클래스를 소개하고 C그에 Something매핑 할 수 있으 려면 Something너무 많은 커플 링 인 수정해야합니다 . 새로운 것을 추가하는 것만으로 SoemthingToCMapper는 덜 방해가됩니다.
Joachim Sauer

1
+1-일반적으로 말하면 OP에서 원하는 것을 달성하려는 경우 (자바에서) 상속보다 구성을 선호해야합니다. 기본 방법을 사용하는 Java 8을 사용하면 더 쉽게 할 수 있지만 모든 사람들이 아직 최첨단을 뛰어 넘을 수는 없습니다. :-).
Martijn Verburg

0

다중 인터페이스를 구현할 수 없으므로 캡슐화 사용을 고려할 수 있습니다. (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 클래스를 작성하는 방법은 무엇입니까? .


-1
public interface IMappable<S, T> {
    T MapFrom(S source);
}

// T - target
// S - source

User를 UserDTO에 매핑하고 User를 UserViewModel에 매핑하려면 두 가지 별도의 구현이 필요합니다. 이 모든 논리를 단일 클래스에 쌓아 두지 마십시오. 그렇게하는 것은 의미가 없습니다.

Joachim을 행복하게 유지하기 위해 업데이트

public interface ITypeConverter<TSource, TDestination>
{
    TDestination Convert(TSource source);
}

그러나 지금 우리는 Automapper 영역에 있습니다 ( http://automapper.codeplex.com/wikipage?title=Custom%20Type%20Converters )


나는 IMappable다른 것들을 매핑하는 것에 대한 좋은 이름 이라고 생각하지 않습니다 . Mapper(또는 IMapper, ;-) 해야하는 경우) 더 정확할 것입니다. (그런데 : 아니, 그건 내 공감대가 아니 었어).
Joachim Sauer

나는 질문에있는 것을 가져 와서 인터페이스라는 사실을 강조하기 위해 I 접두사를 붙였습니다. 네이밍 문제가 아닌 질문에 따라 디자인 문제를 해결하고 있습니다.
CodeART

1
미안하지만 내 생각으로는 디자인 문제를 "해결"하고 이름을 무시할 수는 없습니다. 디자인은 이해할 수있는 구조를 의미합니다. 잘못된 이름 지정은 이해하는 데 문제가됩니다.
Joachim Sauer

업데이트 ;-) 나머지에 당신의 마음을 놓아야합니다
CodeART

1
@CodeART 귀하의 답변을 올바르게 이해했다면 "MapFrom"(소문자 소문자 ;-)이 객체를 생성한다는 것을 의미합니다. 필자의 경우 이미 작성된 객체에 대한 정보를 채우는 것입니다.
estani 10
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.