I came across an interesting problem recently: I want a method in a generics-class to accept only instances of an inner class of the specified generic type only. The goal, illustrated in the following example, is that a CarInspector<CarBrand1>
can only inspect driving wheels manufactured by CarBrand1
, while keeping DrivingWheel
an inner class of CarMaker
. Ther rationale being that I don’t want the DrivingWheel
be defined outside an enclosing CarMaker
subclass.
This was my first approach to the problem:
public abstract class CarMaker {
public abstract class DrivingWheel {}
}
public class CarBrand1 extends CarMaker {
public class DrivingWheelByCarBrand1 extends DrivingWheel {}
private final DrivingWheelByCarBrand1 drivingWheel = new DrivingWheelByCarBrand1();
public DrivingWheelByCarBrand1 getDrivingWheel() {
return drivingWheel;
}
}
public class CarBrand2 extends CarMaker {
private class DrivingWheelByCarBrand2 extends DrivingWheel {}
private final DrivingWheelByCarBrand2 drivingWheel = new DrivingWheelByCarBrand2();
public DrivingWheelByCarBrand2 getDrivingWheel() {
return drivingWheel;
}
}
public class CarInspector<T extends CarMaker> {
public void inspect(T.DrivingWheel arg) {}
}
However, the following code compiles just fine:
CarBrand1 c1 = new CarBrand1();
CarBrand2 c2 = new CarBrand2();
CarInspector<CarBrand1> carInspector = new CarInspector<>();
carInspector.inspect(c1.getDrivingWheel());
carInspector.inspect(c2.getDrivingWheel());
Is there a way so that the compiler throws an error or warning in the line carInspector.inspect(c2.getDrivingWheel())
?
NOTE: this question is besides the fact that the proposed design might not be the best choice and that defining DrivingWheel
as DrivingWheel<T extends CarMaker>
might be more sensible; it’s an interesting tangent nonetheless, and it’s a design alternative I’m considering for the specific domain I’m working at.
You need to use more generics. Change the base DrivingWheel
class to add a generic parameter that specifies the car brand:
public class CarInspector<T extends CarMaker> {
public void inspect(DrivingWheel<T> arg) {}
}