Generic covariance with common methods

I cannot correctly determine the general method when using covariance in a generic class, if at all possible, as I intend. I will best explain the problem with an example.

Say we have the following interface setup for cars

interface Car { ... }
interface SportsCar extends Car { ... }

and such common interfaces for car sellers returning an object Sale

interface CarVendor<C extends Car> {    
  Sale<C> sell(C car);
}

interface SportsCarVendor extends CarVendor<SportsCar> {    
  @Override
  Sale<SportsCar> sell(SportsCar car);
}

Suppose we want our cars to be shared, for example. regarding fuel type:

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<?>.

- ?

+4
2

, , , , , .

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, , :

interface SportsCarVendor extends CarVendor<SportsCar> {    
    @Override
    SportsCarSale sell(SportsCar car);
}
+3

(, ?), , :

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> { }
0

Source: https://habr.com/ru/post/1695076/


All Articles