1

I have next hierarchy of classes

   class MyObject {

}

class FirstChild extends MyObject {

}

class SecondChild extends MyObject {

}

class Calculator<T extends MyObject> {
    public Integer calculateValue(T supperObject) {
        return 10;
    }
}

class IntegerCalculator extends Calculator<FirstChild> {
    @Override
    public Integer calculateValue(FirstChild supperObject) {
        return super.calculateValue(supperObject);
    }
}

class SecondChildCalculator extends Calculator<SecondChild> {
    @Override
    public Integer calculateValue(SecondChild supperObject) {
        return super.calculateValue(supperObject);
    }
}


class AbstractUsefulService {
    protected Calculator<? extends MyObject> calculator;

    public AbstractUsefulService(
        Calculator<? extends MyObject> calculator
    ) {
        this.calculator = calculator;
    }
}

class ImplementationOfAbstractUsefulService extends AbstractUsefulService{

    public ImplementationOfAbstractUsefulService(
        SecondChildCalculator calculator
    ) {
        super(calculator);
    }

    public void doJob(){
        calculator.calculateValue(new SecondChild());
    }
}

I have a big problem here calculator.calculateValue(new SecondChild()); - required ? extends MyObject but found SecondChild. I've read a lot of articles and found only one solution and a generic to AbstractUsefulService and use this generic in ConnectionService, but I don't want to do it. How can I resolve my problem without generic in AbstractUsefulService?

1 Answers1

1

How can I resolve my problem without generic in AbstractUsefulService?

You can't, if you are going to pass the calculator to AbstractUsefulService.

You need to know what type of object the calculator.calculateValue will accept.

The only way to do it would be to keep a reference in the ImplementationOfAbstractUsefulService class:

class ImplementationOfAbstractUsefulService extends AbstractUsefulService{
    private final SecondChildCalculator secondChildCalculator;

    public ImplementationOfAbstractUsefulService(
        SecondChildCalculator calculator
    ) {
        super(calculator);
    }

    public void doJob(){
        secondChildCalculator.calculateValue(new SecondChild());
    }
}
Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • But why? I specify that `calculator.calculateValue` accepts any implementation of MyObject and it doesn't meter which one. what is wrong with this approach ? – Иван Гладуш Feb 13 '20 at 11:09
  • 2
    "I specify that calculator.calculateValue accepts any implementation" No, you've specifed that it takes a *specific* implementation, but you just don't know which one. See [What is PECS](https://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super) – Andy Turner Feb 13 '20 at 11:10