You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 01-default-static-interface-methods.md
+77-18
Original file line number
Diff line number
Diff line change
@@ -1,11 +1,24 @@
1
1
Default and Static Methods for Interfaces
2
2
--------
3
3
4
-
We all understand that we should code to interfaces. Interfaces give client a contract which they should use without relying on the implementation details(i.e. classes). Hence, promoting **[loose coupling](https://en.wikipedia.org/wiki/Loose_coupling)**. Designing clean interfaces is one of the most important aspect of API design. One of the SOLID principle **[Interface segregation](https://en.wikipedia.org/wiki/Interface_segregation_principle)** talks about designing smaller client-specific interfaces instead of designing one general purpose interface. Interface design is the key to clean and effective API's for your libraries and applications.
4
+
We all understand that we should code to interfaces. Interfaces give client a
5
+
contract which they should use without relying on the implementation details
Designing clean interfaces is one of the most important aspect of API design.
8
+
One of the SOLID principle **[Interface segregation](https://en.wikipedia.org/wiki/Interface_segregation_principle)**
9
+
talks about designing smaller client-specific interfaces instead of designing
10
+
one general purpose interface. Interface design is the key to clean and
11
+
effective API's for your libraries and applications.
5
12
6
13
> Code for this section is inside [ch01 package](https://github.com/shekhargulati/java8-the-missing-tutorial/tree/master/code/src/main/java/com/shekhargulati/java8_tutorial/ch01).
7
14
8
-
If you have designed any API then with time you would have felt the need to add new methods to the API. Once API is published it becomes impossible to add methods to an interface without breaking existing implementations. To make this point clear, let's suppose you are building a simple `Calculator` API that supports `add`,`subtract`, `divide`, and `multiply` operations. We can write `Calculator` interface as shown below. ***To keep things simple we will use int.***
15
+
If you have designed any API then with time you would have felt the need to add
16
+
new methods to the API. Once API is published it becomes impossible to add
17
+
methods to an interface without breaking existing implementations. To make this
18
+
point clear, let's suppose you are building a simple `Calculator` API that
19
+
supports `add`,`subtract`, `divide`, and `multiply` operations. We can write
20
+
`Calculator` interface as shown below. ***To keep things simple we will use
21
+
int.***
9
22
10
23
```java
11
24
publicinterfaceCalculator {
@@ -20,7 +33,8 @@ public interface Calculator {
20
33
}
21
34
```
22
35
23
-
To back this `Calculator` interface you created a `BasicCalculator` implementation as shown below.
36
+
To back this `Calculator` interface you created a `BasicCalculator`
37
+
implementation as shown below.
24
38
25
39
```java
26
40
publicclassBasicCalculatorimplementsCalculator {
@@ -52,7 +66,9 @@ public class BasicCalculator implements Calculator {
52
66
53
67
## Static Factory Methods
54
68
55
-
Calculator API turned out to be very useful and easy to use. Users just have to create an instance of `BasicCalculator` and then they can use the API. You start seeing code like the one shown below.
69
+
Calculator API turned out to be very useful and easy to use. Users just have to
70
+
create an instance of `BasicCalculator` and then they can use the API. You start
71
+
seeing code like the one shown below.
56
72
57
73
```java
58
74
Calculator calculator =newBasicCalculator();
@@ -62,17 +78,24 @@ BasicCalculator cal = new BasicCalculator();
62
78
int difference = cal.subtract(3, 2);
63
79
```
64
80
65
-
Oh no!! Users of the API are not coding to `Calculator` interface instead they are coding to implementation. Your API didn't enforced users to code to interfaces as the `BasicCalculator` class was public. If you make `BasicCalculator` package protected then you would have to provide a static factory class that will take care of providing the `Calculator` implementation. Let's improve the code to handle this.
81
+
Oh no!! Users of the API are not coding to `Calculator` interface instead they
82
+
are coding to implementation. Your API didn't enforced users to code to
83
+
interfaces as the `BasicCalculator` class was public. If you make
84
+
`BasicCalculator` package protected then you would have to provide a static
85
+
factory class that will take care of providing the `Calculator` implementation.
86
+
Let's improve the code to handle this.
66
87
67
-
First, we will make `BasicCalculator` package protected so that users can't access the class directly.
88
+
First, we will make `BasicCalculator` package protected so that users can't
89
+
access the class directly.
68
90
69
91
```java
70
92
classBasicCalculatorimplementsCalculator {
71
93
// rest remains same
72
94
}
73
95
```
74
96
75
-
Next, we will write a factory class that will give us the `Calculator` instance as shown below.
97
+
Next, we will write a factory class that will give us the `Calculator` instance
98
+
as shown below.
76
99
77
100
```java
78
101
publicabstractclassCalculatorFactory {
@@ -83,13 +106,26 @@ public abstract class CalculatorFactory {
83
106
}
84
107
```
85
108
86
-
Now, users will be forced to code to `Calculator` interface and they will not have access to implementation details.
109
+
Now, users will be forced to code to `Calculator` interface and they will not
110
+
have access to implementation details.
87
111
88
-
Although we have achieved our goal but we have increased the surface area of our API by adding a new class `CalculatorFactory`. Now users of the API have to learn about one more class before they can use the API effectively. This was the only solution available before Java 8.
112
+
Although we have achieved our goal but we have increased the surface area of our
113
+
API by adding a new class `CalculatorFactory`. Now users of the API have to
114
+
learn about one more class before they can use the API effectively. This was the
115
+
only solution available before Java 8.
89
116
90
-
**Java 8 allows you to declare static methods inside an interface**. This will allow API designers to define static utility methods like `getInstance` in the interface itself. Hence keeping API short and lean. The static methods inside an interface could be used to replace static helper classes(`CalculatorFactory`) that we normally create to define helper methods associated with a type. For example, `Collections` class is a helper class that defines various helper methods to work with Collection and associated interfaces. The methods defined in `Collections` class could easily be added to `Collection` or any of its child interface.
117
+
**Java 8 allows you to declare static methods inside an interface**. This will
118
+
allow API designers to define static utility methods like `getInstance` in the
119
+
interface itself. Hence keeping API short and lean. The static methods inside an
120
+
interface could be used to replace static helper classes(`CalculatorFactory`)
121
+
that we normally create to define helper methods associated with a type. For
122
+
example, `Collections` class is a helper class that defines various helper
123
+
methods to work with Collection and associated interfaces. The methods defined
124
+
in `Collections` class could easily be added to `Collection` or any of its child
125
+
interface.
91
126
92
-
The above code can be improved in Java 8 by adding a static `getInstance` method in the `Calculator` interface itself.
127
+
The above code can be improved in Java 8 by adding a static `getInstance` method
128
+
in the `Calculator` interface itself.
93
129
94
130
```java
95
131
publicinterfaceCalculator {
@@ -111,7 +147,11 @@ public interface Calculator {
111
147
112
148
## Evolving API with time
113
149
114
-
Some of the consumers decided to either extend the `Calculator` API by adding methods like `remainder` or write their own implementation of `Calculator` interface. After talking to your users you came to know that most of them would like to have a `remainder` method added to `Calculator` interface. It looked a very simple API change so you added one more method to the API.
150
+
Some of the consumers decided to either extend the `Calculator` API by adding
151
+
methods like `remainder` or write their own implementation of `Calculator`
152
+
interface. After talking to your users you came to know that most of them would
153
+
like to have a `remainder` method added to `Calculator` interface. It looked a
154
+
very simple API change so you added one more method to the API.
115
155
116
156
```java
117
157
publicinterfaceCalculator {
@@ -132,9 +172,21 @@ public interface Calculator {
132
172
}
133
173
```
134
174
135
-
Adding a method to an interface broke the source compatibility of the API. This means users who were implementing `Calculator` interface would have to add implementation for `remainder` method otherwise their code will not compile. This is a big problem for API designers as it makes API difficult to evolve. Prior to Java 8, it was not possible to have method implementations inside interfaces. This often becomes a problem when it was required to extend an API i.e. adding one or more methods to the interface definition.
136
-
137
-
To allow API's to evolve with time, Java 8 allows users to provide default implementations to methods defined in the interface. These are called **default** or **defender** methods. The class implementing the interface is not required to provide implementation of these methods. If implementing class provides the implementation then implementing class method implementation will be used else default implementation will be used. `List` interface has few default methods defined like `replaceAll`, `sort`, and `splitIterator`.
175
+
Adding a method to an interface broke the source compatibility of the API. This
176
+
means users who were implementing `Calculator` interface would have to add
177
+
implementation for `remainder` method otherwise their code will not compile.
178
+
This is a big problem for API designers as it makes API difficult to evolve.
179
+
Prior to Java 8, it was not possible to have method implementations inside
180
+
interfaces. This often becomes a problem when it was required to extend an API
181
+
i.e. adding one or more methods to the interface definition.
182
+
183
+
To allow API's to evolve with time, Java 8 allows users to provide default
184
+
implementations to methods defined in the interface. These are called
185
+
**default** or **defender** methods. The class implementing the interface is not
186
+
required to provide implementation of these methods. If implementing class
187
+
provides the implementation then implementing class method implementation will
188
+
be used else default implementation will be used. `List` interface has few
189
+
default methods defined like `replaceAll`, `sort`, and `splitIterator`.
We can solve our API problem by defining a default method as shown below. Default methods are usually defined using already existing methods -- `remainder` is defined using `subtract`, `multiply`, and `divide` methods.
201
+
We can solve our API problem by defining a default method as shown below.
202
+
Default methods are usually defined using already existing methods --
203
+
`remainder` is defined using `subtract`, `multiply`, and `divide` methods.
150
204
151
205
```java
152
206
defaultint remainder(int number, int divisor) {
@@ -156,7 +210,11 @@ default int remainder(int number, int divisor) {
156
210
157
211
## Multiple inheritance
158
212
159
-
A class can extend a single class but can implement multiple interfaces. Now that it is feasible to have method implementation in interfaces Java has multiple inheritance of behavior. Java already had multiple inheritance at type level but now it also has multiple inheritance at behavior level. There are three resolution rules that help decide which method will be picked:
213
+
A class can extend a single class but can implement multiple interfaces. Now
214
+
that it is feasible to have method implementation in interfaces Java has
215
+
multiple inheritance of behavior. Java already had multiple inheritance at type
216
+
level but now it also has multiple inheritance at behavior level. There are
217
+
three resolution rules that help decide which method will be picked:
160
218
161
219
**Rule 1: Methods declared in classes win over method defined in interfaces.**
162
220
@@ -179,7 +237,8 @@ class App implements A{
179
237
}
180
238
```
181
239
182
-
This will print `inside App` as methods declared in class have precedence over methods declared in interfaces.
240
+
This will print `inside App` as methods declared in class have precedence over
241
+
methods declared in interfaces.
183
242
184
243
**Rule 2: Otherwise, the most specific interface is selected**
0 commit comments