3

The interface Delayed requires any

implementation of this interface [to] define a compareTo method that provides an ordering consistent with its getDelay method.

However I'm wondering, why there isn't a default implementation in Java 8, as compareTo is required by contract to depend solely on getDelay.

Is there a specific reason why this is left for the implementing class? Or is it impossible to create a default method when overwriting a super interface?

Edit: To make my question more understandable, here is an example:

interface Delayed extends Comparable<Delayed> {

    long getDelay(TimeUnit unit);

    @Override
    default int compareTo(Delayed o) {
      // might not be the perfect "compareTo" implementation, but you get the point
      return o == this? 0:
        Long.compare(this.getDelay(TimeUnit.NANOSECONDS), o.getDelay(TimeUnit.NANOSECONDS);
    }

}
Holger
  • 285,553
  • 42
  • 434
  • 765
Sebastian S
  • 4,420
  • 4
  • 34
  • 63
  • 2
    And how would the default implementation get hold of the necessary _object state_ to perform the computation? An interface has no state! – fge Nov 25 '15 at 14:20
  • 1
    Not only that, but compareTo is highly specific to a class. What would you order an `Object` by? Its reference? Its toString? Its hashcode? – Powerlord Nov 25 '15 at 14:22
  • 1
    @fge @Powerlord as stated above the `compareTo` method is _required_ to provide an ordering depending on `getDelay`, no other information required. Afaik a default method is free to call any sibling method or am I wrong? – Sebastian S Nov 25 '15 at 14:24
  • 1
    You are not wrong but the _contract_ of .getDelay() itself means the Comparable contract can be violated if the delay has expired – fge Nov 25 '15 at 14:37
  • I don't think so. If both delays have elapsed, `compareTo` should return 0. – Sotirios Delimanolis Nov 25 '15 at 14:39
  • 1
    @fge Well to be honest I still don't get the point, as both objects are expired for a _different_ amount of time and thus comparison by difference is still possible. – Sebastian S Nov 25 '15 at 14:40
  • 3
    The contract is not well described. It simply says that 0 or a negative value means that the delay is expired. But it's not clear if a Delayed is free to return anything <= 0 if the delay is expired, if two elapsed delayed are supposed to be equal, or if the delay must continue to evolve in a natural, chonological way (i.e. 1 minute after the limit, it should return -1 minute) – JB Nizet Nov 25 '15 at 14:42
  • @JBNizet with this remark I would have accepted fge's answer (which got deleted by somebody) – Sebastian S Nov 25 '15 at 14:45
  • 1
    FWIW, all the implementations of the JDK, when compared to an instance of a different type of Delayed, use the same algorithm as in the question. When compared to an instance of the same type, they add an additional criteria: a sequence number, in case both instances have the exact same time. Given these implementations, I think the interface could have the default method you're suggesting. – JB Nizet Nov 25 '15 at 14:48

1 Answers1

5

The simple answer is that Delayed exists since 1.5 and default methods exist since 1.8. So in order to provide the compareTo method as default method, the interface has to be deliberately changed.

If that doesn’t happen, there are several possible reasons:

  • It might be that simply no-one ever considered it
  • It might have been considered but dropped because either:

    • There might be possible compatibility issues
    • The expected benefits are not high enough to justify an API change
    • There were things with higher priority to do before the release

To me, it doesn’t look like a high-priority issue. Most of the time you encounter Delayed implementations in the context of ScheduledExecutorServices provided by the JRE and these implementations already exist and therefore won’t benefit from such a change.

I don’t think that you will encounter custom Delayed implementations in application code very often, but even if you see it different, the JRE developers obviously decided to focus on additions whose usefulness is more obvious (or less debatable).


Thinking about it, incorporating the discussion about the getDelay() contract combined with the Comparable contract, it would have been better, if Delayed never extended Comparable at all. After all, it’s not hard to sort objects by a property using a Comparator or similar design pattern.

Community
  • 1
  • 1
Holger
  • 285,553
  • 42
  • 434
  • 765