Sorunuzda başlangıçta bahsettiğiniz konsepte kovaryant dönüş türleri denir .
Kovaryant dönüş türleri çalışır, çünkü bir yöntemin belirli türdeki bir nesneyi döndürmesi gerekir ve geçersiz kılma yöntemleri aslında bir alt sınıfını döndürebilir. Java gibi bir dilin alt tür kurallarına dayanarak S
, bir alt türü ise T
, T
göründüğü her yerde bir S
.
Bu nedenle S
, beklenen bir yöntemi geçersiz kılarken bir geri dönmek güvenlidir T
.
Geçersiz kılma yönteminin, geçersiz kılınan yöntem tarafından talep edilenlerin alt türleri olan bağımsız değişkenler kullandığını kabul etme öneriniz, tür sistemindeki sessizliğe yol açtığı için çok daha karmaşıktır.
Bir yandan, yukarıda belirtilen aynı alt tip kurallarına göre, büyük olasılıkla yapmak istediğiniz şey için zaten çalışır. Örneğin
interface Hunter {
public void hunt(Animal animal);
}
Hiçbir şey, bu sınıfın uygulamalarının herhangi bir hayvan almasını engellemez, bu nedenle sorunuzdaki kriterleri zaten karşılar.
Ancak diyelim ki önerdiğiniz gibi bu yöntemi geçersiz kılabiliriz:
class MammutHunter implements Hunter {
@Override
public void hunt(Mammut animal) {
}
}
İşte komik kısım, şimdi bunu yapabilirsiniz:
AnimalHunter hunter = new MammutHunter();
hunter.hunt(new Bear()); //Uh oh
Kamusal arayüze göre AnimalHunter
herhangi bir hayvanı avlayabilmelisiniz, ancak uygulamanıza göre MammutHunter
sadece Mammut
nesneleri kabul ediyorsunuz . Bu nedenle, geçersiz kılma yöntemi genel arabirimi karşılamaz. Burada sadece yazı sisteminin sağlamlığını kırdık.
Jenerikler kullanarak istediğinizi uygulayabilirsiniz.
interface AnimalHunter<T extends Animal> {
void hunt(T animal);
}
Sonra MammutHunter'ınızı tanımlayabilirsiniz
class MammutHunter implements AnimalHunter<Mammut> {
void hunt(Mammut m){
}
}
Ve jenerik kovaryans ve karşıtlık kullanarak, gerektiğinde kuralları kendi lehinize rahatlatabilirsiniz. Örneğin, bir memeli avcının sadece belirli bir bağlamda kedigilleri avlayabileceğinden emin olabiliriz:
AnimalHunter<? super Feline> hunter = new MammalHunter();
hunter.hunt(new Lion());
hunter.hunt(new Puma());
Diyelim MammalHunter
uygular AnimalHunter<Mammal>
.
Bu durumda bu kabul edilmez:
hunter.hunt(new Mammut()):
Memeler memeliler olsa bile, burada kullandığımız kontravaryant tip üzerindeki kısıtlamalar nedeniyle kabul edilmeyecektir. Yani, bahsettikleriniz gibi şeyler yapmak için türler üzerinde bazı kontrolleri hala deneyebilirsiniz.