this
실제로 클래스 T
의 인스턴스 또는를 확장한다는 보장이 없기 때문에.
예를 들어이 사항을 고려하십시오 T0 extends ExtendComparable<T0>
및 T0는 T0의 슈퍼입니다 : 그것은 바운드 준수로 T0
에서
public class T0 implements ExtendComparable<T0> {...}
public class T1 implements ExtendComparable<T0> {...}
잘 준수합니다. 이 경우 this
은 T0
의 인스턴스이므로 여기에서 문제가 없습니다. 캐스트 (T)this
(따라서 (T0)this
)은 의미가 있습니다. 바인딩은 T0
않음 T1
인가되므로
가 T1
와 선언도 정확 T
은 T0
을 대입한다. 그러나 this
은 T1
이고 T1
은 T0
의 슈퍼 또는 하위가 아닙니다. 예, 둘 다 ExtendedCompatible<T0>
을 구현하지만 형제 사이에서는 전송할 수 없습니다. 예를 들어 Integer 및 Double extend Number는 있지만 (Integer) new Double(0.0)
은 실패합니다. (T)
을 (T0)
로 변환하면 캐스팅도 실패합니다.
당신이 만들고있는 가정은 선언 된 클래스와 동일하게 설정 될 것이고 현재는 그러한 의미를 강제 할 방법이 없다는 것입니다. 이것이 Java 언어의 향후 릴리스에서 어느 시점에서 바뀌기를 희망하지만 Java 언어 "태스크 포스"가 그렇게하는 것을 피하는 실제 이유가있을 것입니다.
캐스팅을 모두 피할 수있는 방법이 있지만 ExtendedCompatible
을 인터페이스가 아닌 추상 클래스로 만들면 더 좋습니다.
당신은 차례로 그 값으로
this
을 통과해야합니다 값이 확장 클래스에 의해 보호되는 생성자에 의해 설정됩니다 유형
T
의 최종 필드를 선언 할 수
:
public abstract class ExtendedCompatible<T extends ExtendedCompatible<? super T>> {
private final T thiz;
protected ExtendedCompatible(final T thiz) {
if (this != thiz) throw new IllegalArgumentException("you must pass yourself");
this.thiz = thiz;
}
...
public class MyExtendedCompatible extends ExtendedCompatible<MyExtendedCompatible> {
public MyExtendedCompatible() {
super(this);
}
}
당신이 지불하는 가격은 여분의 메모리입니다 자체에 대한 어리석은 참조 및 부모 생성자에 this
을 전달하는 코드/CPU 부담이 추가되었습니다.
또 다른는 T
(이) 얻을 수있는 추상 메소드를 선언하는 것입니다 :
// Parent abstract class:
protected abstract T getThiz();
// Child class... for each class:
protected MyChildClass getThiz() { return this; }
이 게시물은 도움이 될 수 있습니다. https://stackoverflow.com/a/25783345/4867374 –