0

The Oracle docs say the following, "Abstract classes are similar to interfaces. You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation. However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods..."

I thought interfaces could only contain abstract methods and abstract methods, by definition, have no implementation. So why do the Java docs say abstract classes are similar to interfaces in that they may contain a mix of methods declared with or without an implementation?

link to the docs

Ell1357
  • 17
  • 1
  • 2
    https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html – Paul Samsotha Sep 10 '22 at 21:21
  • 2
    Because `default` methods for interfaces were added in Java 8 and `private` methods for interfaces were added in Java 9 (the latter support the implementations of the former, if needed). – Slaw Sep 10 '22 at 21:33

2 Answers2

3

Because

I thought interfaces could only contain abstract methods and abstract methods

is incorrect. Or rather, it was correct until java 1.7, and has been incorrect since then, as java8 introduced the interface default methods mechanism. In other words, it has been incorrect for about 15 years at this point.

This is legal java, now:

interface Map<K, V> {
  public V get(Object key);
  public boolean containsKey(Object key);

  public default V getOrDefault(Object key, V defaultValue) {
    return containsKey(key) ? get(key) : defaultValue;
  }
}

default methods blur the lines more between abstract classes and interfaces. Any implementation can override them if it wants. A few rules about them:

  • There is no hierarchy to these. If you define a class that ends up implementsing more than one interface, and this results in inheriting more than one such 'default implementation' for the same method, the compiler will refuse to compile this, and the only way out is to explicitly define that method. You can refer to whatever impl you want using InterfaceName.super.methodName(params); if you like. This 'solves' the "diamond problem" this causes. In other words, the ordering in which you place your interface types in an implements clause still does not matter.
  • interfaces still can't declare fields (or rather, they become constants - implicitly public static final).
  • They are intended for adding utility methods in a version update that are built on top of existing methods, such as getOrDefault (which actually exists) and has done so since java 8). Generally they aren't really 'meant' for expanding on what an interface represents, given that you can't wave a magic wand and get implementors to just grow implementations out of nowhere. In rare cases you can expand on what an interface represents based entirely on default behaviour that doesn't involve any fields. In that specific case, you could use the default mechanism too.
  • The default keyword is required.
  • The same update also included the ability to stick static methods in them, which is nice.
  • You can also write private methods now. This functionality exists solely to let you write helper methods for your default methods.
rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
1

Default methods are a way to put implementation within an interface.

But be aware: Default methods were added to Java to solve the problems of adding support for lambdas without breaking the backward-compatibility for which Java is so famous.

Generally, adding a default method should be a last resort, not your first option.

Usually best to regard an interface as strictly a contract, a promise to be made by a separate class to implement certain behavior.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Personally, I'm also okay with "convenience methods" or "methods that have effectively only one sane implementation" being made `default` as well. Essentially, those are the kind of methods that do not depend directly on the state of the object and only on other methods provided by the interface. – Slaw Sep 10 '22 at 21:52
  • @Slaw Could those "convenience methods" just as well be static methods on a utility class? Is there an upside to putting them on an interface as default methods? The downside is confusing an interface as something other than a contract. – Basil Bourque Sep 10 '22 at 21:54
  • 1
    My answer to that would be, "it depends". For instance, the `Collection` interface has the `isEmpty()` method. The most reasonable and common implementation of that method is `return size() == 0`. That's exactly what the `AbstractCollection` class does. If the collection framework was written today, with default methods, I would make the `isEmpty()` method a default method. I would probably get rid of the `AbstractCollection` class entirely, and just move all implementations into the interface. And it doesn't make sense to have a `Collections.isEmpty(Collection)` method for the same. – Slaw Sep 10 '22 at 22:03
  • But you don't want to add methods to an interface on a whim. It _makes sense_ for a `Collection` to have an `isEmpty()` method. Yet I would leave the `Collections.frequency(Collection,Object)` method where it is (i.e., I wouldn't make that a default method; it does not belong to the interface, in my opinion at least). – Slaw Sep 10 '22 at 22:07