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, covariantListgenel 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 Iterableveya Iterator. Iterator<? extends T>aynı şekilde kullanılabilir Iterator<T>- type parametresinin göründüğü tek yer nextyöntemden dönüş türüdür , bu nedenle güvenli bir şekilde yukarı dönüştürülebilir T. Ancak Suzantılarınız Tvarsa, 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 5bu 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 compareyöntem parametre türü olarak görünür , bu nedenle Tona 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.Datebir 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 variantdemek için böyle değil. super.doSomething("String")ile değiştirilemez sub.doSomething(Object).