泛型方法(有界类型)与继承

Generic method (bounded type) vs 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);
}

逻辑:

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

我知道由于类型擦除导致方法签名冲突,所以我的问题不是“为什么我不能同时拥有这两个方法?”,而是“你会选择哪种方法?”选择?”。

如您所说,视情况而定。您需要记住,泛型是一种编译时工具,可帮助编译器进行一些检查并在您违反约束时吐出错误。

在你的情况下,除了参数类型的上限(AnimalFood)之外,你似乎没有任何可以违反的约束,所以你不会从使用中获得任何好处泛型 - 因此我会选择基于普通继承的方法。

但是,考虑到您正在更改 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> { ... }

现在 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());