2

Let say I have 2 classes called class Cow ad class Pig.

They both implements interface Animal.

For the interface there are only 2 methods called public void eat() and public void speak().

All is fine. But while this seems good making use of interfaces, I thought that if I ever needed to add method(s) to this interface, implementation would break, namely I would need to go implement the new methods in these classes, which breaks the "close-open principle".

So I thought of, in addition to interface, I would make use of abstract class as well, should it be needed that I needed to add new method(s) in the future.

So, for example, public class Cow extends ... implements Animal.

It sounds like a good plan (if it is not, please correct me).

But the problem is, what if these classes extend already some other class? In such case, I could not extend 2 classes.

So my question is:

Is there a pattern where I could declare a common interface of related classes while withholding the ability to add new methods in the future that doesn't break the "closed-open principle" and doesn't break implementations?

Unheilig
  • 16,196
  • 193
  • 68
  • 98
  • 2
    This is the problem that Java 8's [*default methods*](http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html) attempt to address. – Oliver Charlesworth Jun 15 '14 at 10:23

2 Answers2

3

With Java 8 there are default methods

public interface Animal {

    void eat();
    void speak();
    default void sleep(){}

}

Now your Animal must override eat and speak but may choose to override sleep.

Pre Java 8 using a abstract class was the usual way to protect against having to implement every interface method. As you noted, this doesn't work with multiple inheritance so cannot be used to solve all cases.

P.S. don't declare interface methods public, this is the default visibility for all interface members.

Boris the Spider
  • 59,842
  • 6
  • 106
  • 166
  • Thank for response. So, back then when a API designer needed to add new method in next release, how would he go about doing it (if the class already extended another class)? Could you please cite me a sample for this (pre-Java 8)? Thanks. – Unheilig Jun 15 '14 at 10:32
  • @Unheilig for an example, see the class [`Number`](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Number.java), with `intValue` and `longValue` declared as abstract methods, while `byteValue` and `shortValue`, added since Java 1.1, are provided as concrete implementations. – GOTO 0 Jun 15 '14 at 10:39
  • @GOTO0 Thanks. But in this case, `Number` is declared as an `abstract` class instead of an `interface` and by concrete implementation you mean the author declare `abstract concrete` methods in the `abstract` class? That is understandable, but in case where it (`Number`) were an `interface` and let assume the subclass already `extend` another class, this wouldn't work, right? – Unheilig Jun 15 '14 at 10:46
  • @Unheilig no, that wouldn't work. The recommendation in this case is to create a new interface extending the old one with new declarations, which would only become available to newer code. – GOTO 0 Jun 15 '14 at 11:15
  • 1
    @Unheilig I can't find I reference for my claim above, but here's an official tutorial explaining the idea: http://docs.oracle.com/javase/tutorial/java/IandI/nogrow.html – GOTO 0 Jun 15 '14 at 11:18
  • @GOTO0 Thanks, interesting. Sounds noob, but I didn't know an `interface` can `extend` another `interface` like this. – Unheilig Jun 15 '14 at 11:22
1

In Java 8, interfaces can define default methods for this purpose.

GOTO 0
  • 42,323
  • 22
  • 125
  • 158