Khái niệm ban đầu bạn đề cập đến trong câu hỏi của bạn được gọi là các kiểu trả về covariant .
Các kiểu trả về covariant hoạt động vì một phương thức được cho là trả về một đối tượng thuộc loại nhất định và các phương thức ghi đè có thể thực sự trả về một lớp con của nó. Dựa trên các quy tắc phân nhóm của một ngôn ngữ như Java, nếu Slà một kiểu con T, thì bất cứ nơi nào Txuất hiện chúng ta đều có thể vượt qua S.
Vì vậy, an toàn để trả về một Skhi ghi đè một phương thức dự kiến a T.
Đề xuất của bạn để chấp nhận rằng một phương thức ghi đè sử dụng các đối số là các kiểu con của các phương thức được yêu cầu bởi phương thức được ghi đè phức tạp hơn nhiều vì nó dẫn đến sự không rõ ràng trong hệ thống loại.
Một mặt, bởi các quy tắc phân nhóm tương tự được đề cập ở trên, rất có thể nó đã hoạt động cho những gì bạn muốn làm. Ví dụ
interface Hunter {
public void hunt(Animal animal);
}
Không có gì ngăn cản việc triển khai của lớp này nhận được bất kỳ loại động vật nào, vì như vậy nó đã đáp ứng các tiêu chí trong câu hỏi của bạn.
Nhưng giả sử chúng ta có thể ghi đè phương thức này như bạn đề xuất:
class MammutHunter implements Hunter {
@Override
public void hunt(Mammut animal) {
}
}
Đây là phần thú vị, bây giờ bạn có thể làm điều này:
AnimalHunter hunter = new MammutHunter();
hunter.hunt(new Bear()); //Uh oh
Theo giao diện công cộng của AnimalHunterbạn sẽ có thể săn bất kỳ động vật nào, nhưng theo việc thực hiện của MammutHunterbạn, bạn chỉ chấp nhậnMammut các đối tượng. Do đó phương pháp overriden không thỏa mãn giao diện chung. Chúng tôi chỉ phá vỡ sự lành mạnh của hệ thống loại ở đây.
Bạn có thể thực hiện những gì bạn muốn bằng cách sử dụng thuốc generic.
interface AnimalHunter<T extends Animal> {
void hunt(T animal);
}
Sau đó, bạn có thể xác định MammutHunter của bạn
class MammutHunter implements AnimalHunter<Mammut> {
void hunt(Mammut m){
}
}
Và sử dụng hiệp phương sai chung và chống chỉ định, bạn có thể thư giãn các quy tắc có lợi cho bạn khi cần thiết. Chẳng hạn, chúng ta có thể chắc chắn rằng một thợ săn động vật có vú chỉ có thể săn những con mèo trong một bối cảnh nhất định:
AnimalHunter<? super Feline> hunter = new MammalHunter();
hunter.hunt(new Lion());
hunter.hunt(new Puma());
Giả sử MammalHunterthực hiệnAnimalHunter<Mammal> .
Trong trường hợp đó, điều này sẽ không được chấp nhận:
hunter.hunt(new Mammut()):
Ngay cả khi động vật có vú là động vật có vú, nó sẽ không được chấp nhận do những hạn chế đối với loại chống chỉ định mà chúng tôi đang sử dụng ở đây. Vì vậy, bạn vẫn có thể thực hiện một số điều khiển qua các loại để làm những việc như những gì bạn đã đề cập.