답변:
공분산 :
class Super {
Object getSomething(){}
}
class Sub extends Super {
String getSomething() {}
}
Sub # getSomething은 Super # getSomething 반환 유형의 하위 클래스를 반환하기 때문에 공변 적입니다 (그러나 Super.getSomething ()의 계약을 완전히 채 웁니다).
반 변성
class Super{
void doSomething(String parameter)
}
class Sub extends Super{
void doSomething(Object parameter)
}
Sub # doSomething은 Super # doSomething 매개 변수의 수퍼 클래스 매개 변수를 취하기 때문에 반 변성입니다 (하지만 Super # doSomething의 계약을 완전히 채 웁니다).
주의 :이 예제는 Java에서 작동하지 않습니다. Java 컴파일러는 doSomething ()-Method를 오버로드하고 재정의하지 않습니다. 다른 언어는이 스타일의 반 변성을 지원합니다.
제네릭
Generics에서도 가능합니다.
List<String> aList...
List<? extends Object> covariantList = aList;
List<? super String> contravariantList = aList;
이제 covariantList
일반 매개 변수를 사용하지 않는 모든 메소드에 액세스 할 수 있지만 ( "extends Object" 여야 하므로) getter는 제대로 작동합니다 (반환 된 객체는 항상 "Object"유형이 됨).
반대의 경우 contravariantList
: 일반 매개 변수를 사용하여 모든 메소드에 액세스 할 수 있지만 ( "String"의 수퍼 클래스 여야하므로 항상 하나를 전달할 수 있음) getter는 없습니다 (반환 된 유형은 String의 다른 수퍼 유형일 수 있습니다. )
공분산 : Iterable 및 Iterator. 공변량 Iterable
또는 Iterator
. Iterator<? extends T>
단지로 사용할 수 있습니다 Iterator<T>
유형 매개 변수가 나타납니다가의 리턴 타입 유일한 장소 - next
이 안전하게 최대 캐스트 할 수 있도록, 방법 T
. 그러나 S
extends 가있는 경우 유형의 변수에 T
할당 할 수도 있습니다 . 예를 들어 find 메소드를 정의하는 경우 :Iterator<S>
Iterator<? extends T>
boolean find(Iterable<Object> where, Object what)
List<Integer>
및 로 호출 할 수 5
없으므로 다음과 같이 더 잘 정의됩니다.
boolean find(Iterable<?> where, Object what)
Contra-variance : Comparator. 거의 항상 사용하는 것이 합리적입니다.. 그대로 사용할 Comparator<? super T>
수 있기 때문 Comparator<T>
입니다. 유형 매개 변수는 compare
메소드 매개 변수 유형 으로 만 표시 되므로 T
안전하게 전달할 수 있습니다. 예를 들어 DateComparator implements Comparator<java.util.Date> { ... }
a가 List<java.sql.Date>
있고 해당 비교기 로 정렬하려는 경우 (은의 java.sql.Date
하위 클래스 임 java.util.Date
) 다음과 같이 할 수 있습니다.
<T> void sort(List<T> what, Comparator<? super T> how)
하지만
<T> void sort(List<T> what, Comparator<T> how)
상기 봐 Liskov 대체 원칙 . 실제로 B 클래스가 A 클래스를 확장하면 A가 필요할 때마다 B를 사용할 수 있어야합니다.
contra variant
말할 경우가 아닙니다 . super.doSomething("String")
로 대체 할 수 없습니다 sub.doSomething(Object)
.