Konsep yang awalnya Anda rujuk dalam pertanyaan Anda disebut tipe pengembalian kovarian .
Tipe kembalinya kovarian bekerja karena metode seharusnya mengembalikan objek tipe tertentu dan metode utama sebenarnya dapat mengembalikan subkelasnya. Berdasarkan aturan subtyping dari bahasa seperti Java, jika S
merupakan subtipe T
, maka di mana pun T
muncul kita bisa melewati a S
.
Karena itu, aman untuk mengembalikan sebuah S
ketika mengganti metode yang diharapkan a T
.
Saran Anda untuk menerima bahwa metode penimpaan menggunakan argumen yang merupakan subtipe dari yang diminta oleh metode penimpaan jauh lebih rumit karena mengarah pada ketidakberesan dalam sistem tipe.
Di satu sisi, dengan aturan subtyping yang sama yang disebutkan di atas, kemungkinan besar itu sudah berfungsi untuk apa yang ingin Anda lakukan. Contohnya
interface Hunter {
public void hunt(Animal animal);
}
Tidak ada yang mencegah implementasi kelas ini dari menerima hewan apa pun, karena sudah memenuhi kriteria dalam pertanyaan Anda.
Tetapi mari kita anggap kita dapat mengganti metode ini seperti yang Anda sarankan:
class MammutHunter implements Hunter {
@Override
public void hunt(Mammut animal) {
}
}
Inilah bagian yang lucu, sekarang Anda bisa melakukan ini:
AnimalHunter hunter = new MammutHunter();
hunter.hunt(new Bear()); //Uh oh
Sesuai antarmuka publik AnimalHunter
Anda harus dapat berburu binatang apa pun, tetapi sesuai penerapan MammutHunter
Anda, Anda hanya menerima Mammut
benda. Oleh karena itu metode overriden tidak memuaskan antarmuka publik. Kami baru saja mematahkan tingkat kesehatan sistem tipe di sini.
Anda dapat menerapkan apa yang Anda inginkan dengan menggunakan obat generik.
interface AnimalHunter<T extends Animal> {
void hunt(T animal);
}
Maka Anda bisa mendefinisikan MammutHunter Anda
class MammutHunter implements AnimalHunter<Mammut> {
void hunt(Mammut m){
}
}
Dan menggunakan kovarians generik dan contravariance, Anda dapat melonggarkan aturan yang menguntungkan Anda saat diperlukan. Misalnya kita bisa memastikan bahwa pemburu mamalia hanya bisa berburu kucing dalam konteks tertentu:
AnimalHunter<? super Feline> hunter = new MammalHunter();
hunter.hunt(new Lion());
hunter.hunt(new Puma());
Seandainya MammalHunter
alat AnimalHunter<Mammal>
.
Dalam hal ini ini tidak akan diterima:
hunter.hunt(new Mammut()):
Bahkan ketika mamut adalah mamalia, ia tidak akan diterima karena pembatasan pada jenis contravarian yang kami gunakan di sini. Jadi, Anda masih dapat menjalankan beberapa kontrol atas jenis untuk melakukan hal-hal seperti yang Anda sebutkan.