weh*_*tyk 7 java generics casting type-safety
这是我的第一个问题,我希望它对读者和我自己都足够有用!在过去的两天里,我用Google搜索并躲过了这个世界.
我有抽象的模型和存储类,从中派生出具体的模型和存储类:
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
}
}
Run Code Online (Sandbox Code Playgroud)
没问题.现在,我希望能够save()
直接在一个Apple
实例上调用它,将其持久化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
}
}
Run Code Online (Sandbox Code Playgroud)
哪个有效,但是IntelliJ给了我关于未经检查的演员的警告save()
.的确,我正在Food<T,S>
向T
.
问题:如何apple.save()
以类型安全的方式实现此功能?
我不希望出现在客户端代码中的任何通配符,因此更改abstract void setFood(T food);
到abstract <Z extends Food<T,S>> void setFood(Z food);
是解决不了问题.(显然我SupressWarnings("unchecked")
也在避免).
我知道Java Generics,在使用类层次结构时如何避免未经检查的赋值警告?,Generics演员问题,以及the get-put原则,但我仍然无法理解它.
提前致谢!
我认为食物和它的存储之间存在相互依赖性,这似乎是一个值得怀疑的设计.单向依赖会极大地简化泛型:
class Food { ... }
class FoodStorage<F extends Food> {
void setFood(F f);
}
Run Code Online (Sandbox Code Playgroud)
但是如果你坚持相互依赖,你可以在没有演员表的情况下做到如下:
abstract class Food<F extends Food<F, S>, S extends FoodStorage<F, S>> {
abstract F getThis();
abstract S getStorage();
void save() {
getStorage().setFood(getThis());
}
}
abstract class FoodStorage<F extends Food<F, S>, S extends FoodStorage<F, S>> {
abstract void setFood(F food);
}
Run Code Online (Sandbox Code Playgroud)