jwp*_*pol 1 java generics inheritance
我有一个典型的问题什么更好,我认为答案总是视情况而定,但无论如何我想澄清一下。所以有两种方法:
public static <A extends Animal, F extends Food> void feed(A animal, F food) {
animal.setFood(food);
}
public static void feed(Animal animal, Food food) {
animal.setFood(food);
}
Run Code Online (Sandbox Code Playgroud)
和逻辑:
Cat cat = new Cat(); // Cat is a child of Animal
Dog dog = new Dog(); // Dog is a child of Animal
Pork pork = new Pork(); // Pork is a child of Food
pork.setName("Whiskas");
Beef beef = new Beef(); // Beef is a child of Food
beef.setName("Pedigree");
AnimalService.feed(cat, beef);
AnimalService.feed(dog, pork);
cat.eat(); // prints I'm eating Pedigree
dog.eat(); // prints I'm eating Whiskas
Run Code Online (Sandbox Code Playgroud)
我知道由于类型擦除而存在方法签名冲突,所以我的问题不是“为什么我不能同时使用这两种方法?”,而是“你会选择哪种方法?”。
正如你所说,这取决于。您需要记住,泛型是一种编译时工具,可以帮助编译器进行一些检查,并在违反约束时吐出错误。
Animal在您的情况下,除了参数类型(和)的上限之外,您似乎没有任何要违反的约束,Food因此您不会从使用泛型中获得任何好处 - 因此我会选择基于普通继承的方法。
但是,考虑一下您正在更改Animal接口来定义动物所需的食物种类(从而添加继承无法帮助您在编译时强制执行的约束):
interface Animal<F extends Food> { ... }
class DogFood implements Food { ... }
class CatFood implements Food { ... }
class Whiskas extends CatFood { ... }
class Dog implements Animal<DogFood> { ... }
class Cat implements Animal<CatFood> { ... }
Run Code Online (Sandbox Code Playgroud)
现在feed()可以使用泛型让编译器帮助您选择正确的食物类型:
<F extends Food> void feed(Animal<F> animal, F food) { ... }
//this should compile because Cat defines Food needs to be CatFood
feed(new Cat(), new CatFood());
//this should also compile because Whiskas is CatFood
feed(new Cat(), new Whiskas());
//this shouldn't compile because DogFood is not CatFood
feed(new Cat(), new DogFood());
Run Code Online (Sandbox Code Playgroud)