Yanıtlar:
Kovaryans:
class Super {
Object getSomething(){}
}
class Sub extends Super {
String getSomething() {}
}
Sub # getSomething, Super # getSomething'in dönüş türünün bir alt sınıfını döndürdüğü için eş değişkendir (ancak Super.getSomething () sözleşmesini doldurur)
Kontraviyans
class Super{
void doSomething(String parameter)
}
class Sub extends Super{
void doSomething(Object parameter)
}
Sub # doSomething, Super # doSomething parametresinin bir üst sınıfının bir parametresini aldığı için aykırıdır (ancak yine, Super # doSomething sözleşmesini doldurur)
Dikkat: Bu örnek Java'da çalışmaz. Java derleyicisi aşırı yüklenir ve doSomething () - Yöntemini geçersiz kılmaz. Diğer diller bu tarz kontraverice desteklemektedir.
Jenerikler
Bu, Jenerikler için de mümkündür:
List<String> aList...
List<? extends Object> covariantList = aList;
List<? super String> contravariantList = aList;
Artık, covariantList
genel bir parametre almayan tüm yöntemlerine erişebilirsiniz (çünkü bu , "Nesneyi genişleten" bir şey olmalıdır ), ancak alıcılar iyi çalışacaktır (döndürülen nesne her zaman "Nesne" türünde olacaktır)
Bunun tersi şunun için doğrudur contravariantList
: Genel parametrelerle tüm yöntemlere erişebilirsiniz (bunun "Dize" nin bir üst sınıfı olması gerektiğini bilirsiniz, böylece her zaman birini geçebilirsiniz), ancak alıcı yok (Döndürülen tür, String'in başka herhangi bir üst türü olabilir )
Eş varyans: Yinelenebilir ve Yineleyici. Bir eş değişken Iterable
veya Iterator
. Iterator<? extends T>
aynı şekilde kullanılabilir Iterator<T>
- type parametresinin göründüğü tek yer next
yöntemden dönüş türüdür , bu nedenle güvenli bir şekilde yukarı dönüştürülebilir T
. Ancak S
uzantılarınız T
varsa, Iterator<S>
bir tür değişkenine de atayabilirsiniz Iterator<? extends T>
. Örneğin, bir bulma yöntemi tanımlıyorsanız:
boolean find(Iterable<Object> where, Object what)
ile arayamayacaksınız List<Integer>
ve 5
bu nedenle daha iyi
boolean find(Iterable<?> where, Object what)
Ters varyans: Karşılaştırıcı. Kullanımı neredeyse her zaman mantıklıdır Comparator<? super T>
çünkü aynı şekilde kullanılabilir Comparator<T>
. Tür parametresi yalnızca compare
yöntem parametre türü olarak görünür , bu nedenle T
ona güvenli bir şekilde geçirilebilir. Örneğin, bir a'nız varsa DateComparator implements Comparator<java.util.Date> { ... }
ve List<java.sql.Date>
bu karşılaştırıcıyla bir sıralamak istiyorsanız ( java.sql.Date
bir alt sınıfıdır java.util.Date
), şunları yapabilirsiniz:
<T> void sort(List<T> what, Comparator<? super T> how)
ama beraber değil
<T> void sort(List<T> what, Comparator<T> how)
Bak Liskov ikame prensibi . Aslında, B sınıfı A sınıfını genişletirse, o zaman bir A gerektiğinde bir B kullanabilmelisiniz.
contra variant
demek için böyle değil. super.doSomething("String")
ile değiştirilemez sub.doSomething(Object)
.