Programing

제네릭으로 인터페이스를 구현하는 Java 추상 클래스

lottogame 2020. 11. 22. 18:49
반응형

제네릭으로 인터페이스를 구현하는 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;
    }

}

다른 해결책을 찾았습니다.

  1. comaprable을 구성하는 필드에 인터페이스를 정의하십시오 (예 : ComparableFoo).
  2. Implement the interface on the parent class
  3. Implement Comparable on the parent class.
  4. 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'

참고URL : https://stackoverflow.com/questions/3592939/java-abstract-class-implementing-an-interface-with-generics

반응형