当在泛型类上使用协方差时,我无法正确定义泛型方法,如果这是我想要的方式。我最好通过例子来解释手头的问题。
假设我们有以下汽车接口设置
interface Car { ... }
interface SportsCar extends Car { ... }
和汽车供应商返回Sale
对象
interface CarVendor<C extends Car> {
Sale<C> sell(C car);
}
interface SportsCarVendor extends CarVendor<SportsCar> {
@Override
Sale<SportsCar> sell(SportsCar car);
}
现在我们假设我们希望我们的汽车是通用的,例如关于燃料类型:
interface Car<F extends FuelType> { ... }
interface SportsCar<F extends FuelType> extends Car<F> { ... }
class PetrolSportsCar extends SportsCar<Petrol> { ... }
class DieselSportsCar extends SportsCar<Diesel> { ... }
如果我们不想为任何燃料销售汽车,我们在重新定义供应商界面时会遇到问题。通用方法似乎是答案,但我无法正确定义它,因为在类上定义了通用Car<?>
,但应在方法上定义通用FuelType
。得到这个想法:
interface CarVendor<C extends Car<?>> {
<F extends FuelType> Sale<Car<F>> sell(Car<F> param);
}
interface SportsCarVendor extends CarVendor<SportsCar<?>> {
@Override
<F extends FuelType> Sale<SportsCar<F>> sell(SportsCar<F> param);
}
由于签名SportsCarVendor
与预期类型sell(SportsCar<F>)
不匹配, SportsCar<?>
显然无法编译。
有人可以为这个问题提供可行的解决方案吗?
答案 0 :(得分:3)
从目前为止提供的内容来看,我没有看到任何理由为什么大多数接口和类应该是通用的,并且我看到为什么大多数不应该是通用的原因。
FuelType
听起来应该是Car
的属性,而不是类型参数。也许它可以声明为枚举,具体取决于您的具体要求。
enum FuelType {
PETROL,
DIESEL;
}
public class Car {
private FuelType fuelType;
// rest of implementation
}
同样,Car
应该是Sale
的属性,而不是类型参数。
public class Sale {
private Car sold;
// rest of implementation
}
您可能仍然需要SportsCarVendor
是通用的,以便您可以缩小实施类可以销售的car
类型,但Sale
sell
方法仍会返回不需要是通用的。
interface CarVendor<C extends Car> {
Sale sell(C car);
}
interface SportsCarVendor extends CarVendor<SportsCar> {
@Override
Sale sell(SportsCar car);
}
此外,如果您碰巧需要Sale
的特定子类,例如SportsCarSale
,那么你可以使用return-type covariance,这是一个子类在没有泛型的情况下缩小返回类型的能力:
interface SportsCarVendor extends CarVendor<SportsCar> {
@Override
SportsCarSale sell(SportsCar car);
}
答案 1 :(得分:0)
如果您真的必须为每个汽车供应商单独处理燃料类型(可能是税务原因?),您可以通过以下方式定义汽车供应商以实现此目的:
interface CarVendor<F extends FuelType, C extends Car<F>> {
Sale<C> sell(C param);
}
interface SportsCarVendor <F extends FuelType> extends CarVendor<F, SportsCar<F>> { }
现在具体实现:
class SportsCarVendorDiesel implements SportsCarVendor<DieselFuel> {
@Override
public Sale<SportsCar<DieselFuel>> sell(SportsCar<DieselFuel> param) {
return null;
}
}
class SportsCarVendorGas implements SportsCarVendor<GasolineFuel> {
@Override
public Sale<SportsCar<GasolineFuel>> sell(SportsCar<GasolineFuel> param) {
return null;
}
}
我使用的其他类都是这样的:
interface FuelType {
double burnRate();
}
class DieselFuel implements FuelType {
@Override
public double burnRate() {
return 0;
}
}
class GasolineFuel implements FuelType {
@Override
public double burnRate() {
return 0;
}
}
interface Car<F extends FuelType> { }
interface SportsCar<F extends FuelType> extends Car<F> { }
class Sale<C> { }