제네릭으로 인터페이스를 구현하는 Java 추상 클래스
Comparable을 구현하는 추상 클래스를 정의하려고합니다. 다음 정의로 클래스를 정의 할 때 :
public abstract class MyClass implements Comparable <MyClass>
하위 클래스는 compareTo(MyClass object)
. 대신 모든 하위 클래스가 compareTo(SubClass object)
자체 유형의 객체를 허용하여 구현하기를 원합니다 . 다음과 같이 추상 클래스를 정의하려고 할 때 :
public abstract class MyClass implements Comparable <? extends MyClass>
"수퍼 타입은 와일드 카드를 지정할 수 없습니다."라고 불평합니다.
해결책이 있습니까?
제 생각에는 너무 장황하지만 작동합니다.
public abstract class MyClass<T extends MyClass<T>> implements Comparable<T> {
}
public class SubClass extends MyClass<SubClass> {
@Override
public int compareTo(SubClass o) {
// TODO Auto-generated method stub
return 0;
}
}
서명을 선언 할 때 발생하는 기계적 어려움을 제외하고는 목표가별로 의미가 없습니다. 파생 클래스가 조정할 수있는 인터페이스를 설정하는 전체 아이디어를 깨뜨리는 공변 비교 함수를 설정하려고합니다.
SubClass
인스턴스를 다른 SubClass
인스턴스 와 만 비교할 수 있도록 일부 하위 클래스를 정의하는 경우에 SubClass
정의 된 계약 을 어떻게 충족 MyClass
합니까? 리콜은 MyClass
그것과 그것에서 파생 된 유형이 다른 비교 될 수 있음을 말하고있다 MyClass
인스턴스. 당신을위한이 아닌 진정한 만들려고 SubClass
하는 수단, SubClass
만족하지 않는다 MyClass
'의 계약을 : 당신은 대체 할 수 SubClass
에 대한 MyClass
때문에 SubClass
의 요구 사항이 엄격하다.
이 문제는 공분산과 반공 분산에 중점을두고 있으며, 유형 파생을 통해 함수 시그니처를 변경하는 방법에 중점을 둡니다. 인수 유형에 대한 요구 사항을 완화 할 수 있습니다 ( 수퍼 유형의 서명 요구 사항보다 더 넓은 유형을 허용 함). 반환 유형에 대한 요구 사항을 강화 하여 수퍼 유형의 서명보다 좁은 유형을 반환하도록 약속 할 수 있습니다 . 이러한 각 자유는 여전히 상위 유형에 대한 파생 유형의 완벽한 대체를 허용합니다. 호출자는 상위 유형의 인터페이스를 통해 파생 유형을 사용할 때 차이를 구분할 수 없지만 파생 유형을 사용하는 호출자는 이러한 자유를 구체적으로 활용할 수 있습니다.
Willi의 대답 은 일반적인 선언에 대해 가르쳐 주지만 의미론을 희생하면서 기술을 받아들이 기 전에 목표를 재고 할 것을 촉구합니다.
Java의 자체 예를 참조하십시오.
public abstract class Enum<E extends Enum<E>> implements Comparable<E>
public final int compareTo(E o)
seh의 의견 : 일반적으로 주장이 정확합니다. 그러나 제네릭은 유형 관계를 더 복잡하게 만듭니다. 하위 클래스는 Willi의 솔루션에서 MyClass의 하위 유형이 아닐 수 있습니다 ....
SubClassA
의 하위 유형 MyClass<SubClassA>
이지만의 하위 유형은 아닙니다.MyClass<SubClassB>
type MyClass<X>
은 compareTo(X)
모든 하위 유형이 준수해야하는 계약을 정의 합니다. 거기에는 문제가 없습니다.
캡처가 필요한지 잘 모르겠습니다.
먼저 compareTo를 추상 클래스에 추가합니다.
public abstract class MyClass implements Comparable <MyClass> {
@Override
public int compareTo(MyClass c) {
...
}
}
그런 다음 구현을 추가하십시오 ...
public class MyClass1 extends MyClass {
...
}
public class MyClass2 extends MyClass {
...
}
비교를 호출하면 슈퍼 유형 메서드가 호출됩니다.
MyClass1 c1 = new MyClass1();
MyClass2 c2 = new MyClass2();
c1.compareTo(c2);
public abstract class MyClass<T> implements Comparable<T> {
}
public class SubClass extends MyClass<SubClass> {
@Override
public int compareTo(SubClass o) {
// TODO Auto-generated method stub
return 0;
}
}
다른 해결책을 찾았습니다.
- comaprable을 구성하는 필드에 인터페이스를 정의하십시오 (예 : ComparableFoo).
- Implement the interface on the parent class
- Implement Comparable on the parent class.
- Write your implementation.
Solution should look like this:
public abstract class MyClass implements ComparableFoo,Comparable<ComparableFoo> {
public int compareTo(ComparableFoo o) {
// your implementation
}
}
This solution implies that more things might implement ComparableFoo - this is likely not the case but then you're coding to an interface and the generics expression is simple.
I know you said you want "compareTo(SubClass object), accepting an object of its own type", but I still suggest declaring the abstract class like this:
public abstract class MyClass implements Comparable <Object>
and do an instanceof check when overriding compareTo in MySubClass:
@Override
public int compareTo(Object o) {
if (o instanceof MySubClass)) {
...
}
else throw new IllegalArgumentException(...)
}
similarly to 'equals' or 'clone'
'Programing' 카테고리의 다른 글
Java 8에서 "기능적 인터페이스"의 정확한 정의 (0) | 2020.11.22 |
---|---|
PHP 구성 : 시스템의 시간대 설정에 의존하는 것은 안전하지 않습니다. (0) | 2020.11.22 |
NaN ^ 0 == 1 인 이유 (0) | 2020.11.22 |
Entity Framework 6.0의 ORM 엔터티 대 도메인 엔터티 (0) | 2020.11.22 |
Visual Studio 2013에서 .less 파일에서 CSS 파일을 생성 할 수 있나요? (0) | 2020.11.22 |