Java'da hem aşırı yükleme hem de geçersiz kılma durumlarında kovaryans ve kontravarlık gösteren işlevlere örnekler verin. [kapalı]


Yanıtlar:


155

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 )


79
İlk kontraverans örneği Java'da çalışmaz. Sub sınıfındaki doSomething () bir aşırı yüklemedir, geçersiz kılma değildir.
Craig P. Motlin

15
Aslında. Java, alt tiplemede çelişkili argümanları desteklemez. Yalnızca hangi ilgili yöntemin dönüş türleri için kovaryans (ilk örnekteki gibi).
the_dark_destructor

Mükemmel cevap. Kovaryans bana mantıklı görünüyor. Ama bana JLS'de kontravansı tanımlayan bir paragraf gösterebilir misiniz? Neden Sub.doSomething çağrılır?
Mikhail

2
Craig'in işaret ettiği gibi, öyle değil. Bence burada geçersiz kılma ve aşırı yükleme arasında bir çatışma var ve SUN (her zaman olduğu gibi) geriye dönük uyumlu seçeneği seçti. Yani Java'da bir yöntemi geçersiz kılarken karşıt parametreleri kullanamazsınız.
2013

1
Cevabıma neden olumsuz oy verdiğimi bilmek güzel.
kodlanmış

48

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)

-4

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.


6
Bu soruya cevap vermiyor ve yanıltıcı. Anlamsal doğruluğu bozan ve dolayısıyla LSP'yi ihlal eden bir değişken sistem tasarlamak tamamen mümkün olacaktır.
Matt Whipple

bu contra variantdemek için böyle değil. super.doSomething("String")ile değiştirilemez sub.doSomething(Object).
zinking

Sorun bu değil
OlivierTerrien
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.