2

Could someone point me out the reason why default interface methods cannot define behavior/implementation for other interface methods implemented by a certain class, please?

interface Transformable {
    int quarter();
    BigDecimal value();
}

interface Quarterly {

    int getQuarter();

    void setQuarter(int quarter);

    // Method that I would expect to be used to define Transformable method behavior
    default int quarter() {
        return getQuarter();
    }
}

// expects quarter() implementation
static class SomethingQuarterly implements Quarterly, Transformable {

    private int quarter;
    private BigDecimal value;

    @Override
    public int getQuarter() {
        return quarter;
    }

    @Override
    public void setQuarter(int quarter) {
        this.quarter = quarter;
    }

    @Override
    public BigDecimal value() {
        return value;
    }
}
Michael
  • 41,989
  • 11
  • 82
  • 128

2 Answers2

4

The problem is that if Transformable::quarter were to change to a default method, which should be a backwards compatible change from the interface's perspective, it would cause the diamond problem. Which of the two defaults would get chosen?

The compiler doesn't know, of course, and so the safest thing is to make the person writing the implementation resolve the problem even though the problem doesn't exist yet. By making the implementer resolve the ambiguity, Transformable::quarter can change to a default method in the future without breaking SomethingQuarterly.

If the two methods are conceptually related and Quarterly should override Transformable, you should make Quarterly extend that interface.

interface Quarterly extends Transformable {
    //...
}
Michael
  • 41,989
  • 11
  • 82
  • 128
  • Ok @Michael, I think you clarified it when you pointed out the backward compatibility. A possible Transformable::quarter default later implementation would break the 'clients'. – VeryNiceArgumentException Mar 20 '20 at 08:58
1

To make it work, your Quarterly interface has to inherit from the Transformable interface. Thus, do the following modification:

interface Quarterly extends Transformable {

    int getQuarter();

    void setQuarter(int quarter);

    // Method that I would expect to be used to define Transformable method behavior
    default int quarter() {
        return getQuarter();
    }
}

After this, your SomethingQuarterly class can implement just the Quarterly interface.

PetoPeto
  • 21
  • 7