这是我的第一个 SO 问题,我希望它对读者和我自己都足够有用!在过去的两天里,我用谷歌搜索并避开了这个世界。
我有抽象模型和存储类,从中派生出具体模型和存储类:
abstract class Food {}
abstract class FoodStorage<T extends Food> {
abstract void setFood(T food);
}
class Apple extends Food {}
class Basket extends FoodStorage<Apple> {
@Override
void setFood(Apple apple) {
// Save that apple to the basket
}
}
没问题。现在,我希望能够save()
直接在Apple
实例上调用 a ,将其持久Basket
化(无需担心篮子),并在抽象类中实现它。我发现的最好的是:
abstract class Food<T extends Food<T,S>,
S extends FoodStorage<T,S>> {
abstract S getStorage();
void save() {
getStorage().setFood((T)this); // <---- Unchecked cast warning
}
}
abstract class FoodStorage<T extends Food<T,S>, S extends FoodStorage<T,S>> {
abstract void setFood(T food);
}
class Apple extends Food<Apple,Basket> {
Basket basket = new Basket(); // or Basket.getInstance();
@Override
Basket getStorage() {
return basket;
}
}
class Basket extends FoodStorage<Apple,Basket> {
@Override
void setFood(Apple apple) {
// Save that apple to the basket
}
}
哪个有效,但 IntelliJ 给了我一个关于未经检查的演员表的警告save()
。确实,我正在从Food<T,S>
to投射T
。
问题:如何apple.save()
以类型安全的方式实现它?
我不希望客户端代码中出现任何通配符,因此更改abstract void setFood(T food);
为abstract <Z extends Food<T,S>> void setFood(Z food);
不是解决方案。(显然我SupressWarnings("unchecked")
也在避免)。
我知道Java 泛型,如何在使用类层次结构时避免未经检查的赋值警告?,泛型演员问题,以及get-put 原则,但我仍然无法理解它。
提前致谢!