Tolong tunjukkan contoh yang baik untuk kovariansi dan kontravarian di Jawa.
sumber
Tolong tunjukkan contoh yang baik untuk kovariansi dan kontravarian di Jawa.
Kovarian:
class Super {
Object getSomething(){}
}
class Sub extends Super {
String getSomething() {}
}
Sub # getSomething adalah kovarian karena mengembalikan subclass dari tipe kembalian Super # getSomething (tetapi memenuhi kontrak Super.getSomething ())
Kontravarian
class Super{
void doSomething(String parameter)
}
class Sub extends Super{
void doSomething(Object parameter)
}
Sub # doSomething adalah contravariant karena mengambil parameter superclass dari parameter Super # doSomething (tapi, sekali lagi, memenuhi kontrak Super # doSomething)
Perhatikan: contoh ini tidak berfungsi di Java. Compiler Java akan membebani dan tidak mengganti metode doSomething () -. Bahasa lain mendukung gaya kontravarian ini.
Generik
Ini juga mungkin untuk Generik:
List<String> aList...
List<? extends Object> covariantList = aList;
List<? super String> contravariantList = aList;
Anda sekarang dapat mengakses semua metode covariantList
yang tidak mengambil parameter umum (karena harus berupa sesuatu yang "memperluas Objek"), tetapi getter akan berfungsi dengan baik (karena objek yang dikembalikan akan selalu berjenis "Objek")
Hal yang sebaliknya berlaku untuk contravariantList
: Anda dapat mengakses semua metode dengan parameter generik (Anda tahu itu pasti kelas super dari "String", sehingga Anda selalu dapat meneruskan satu), tetapi tidak ada getter (Jenis yang dikembalikan mungkin dari supertipe String lainnya )
Co-variance: Iterable dan Iterator. Hampir selalu masuk akal untuk mendefinisikan co-varian
Iterable
atauIterator
.Iterator<? extends T>
dapat digunakan sama sepertiIterator<T>
- satu-satunya tempat di mana parameter tipe muncul adalah tipe kembalian darinext
metode, sehingga dapat dengan aman di-up-castT
. Tetapi jika Anda memilikiS
perluasanT
, Anda juga dapat menetapkanIterator<S>
ke tipe variabelIterator<? extends T>
. Misalnya jika Anda mendefinisikan metode find:Anda tidak akan dapat memanggilnya dengan
List<Integer>
dan5
, jadi lebih baik didefinisikan sebagaiKontra-varian: Pembanding. Hampir selalu masuk akal untuk digunakan
Comparator<? super T>
, karena dapat digunakan sama sepertiComparator<T>
. Parameter tipe muncul hanya sebagaicompare
tipe parameter metode, sehinggaT
dapat diteruskan dengan aman. Misalnya jika Anda memilikiDateComparator implements Comparator<java.util.Date> { ... }
dan ingin mengurutkanList<java.sql.Date>
dengan pembanding itu (java.sql.Date
adalah sub-kelas darijava.util.Date
), Anda dapat melakukannya dengan:tapi tidak dengan
sumber
Lihatlah prinsip substitusi Liskov . Akibatnya, jika kelas B memperluas kelas A maka Anda harus dapat menggunakan B setiap kali A diperlukan.
sumber
contra variant
dikatakan.super.doSomething("String")
tidak bisa digantikan olehsub.doSomething(Object)
.