Skip to content

Commit 1cdbe24

Browse files
blakehawkinsshekhargulati
authored andcommitted
reflow paragraphs to use 80-character gutter (#5)
1 parent 7d84b55 commit 1cdbe24

File tree

1 file changed

+77
-18
lines changed

1 file changed

+77
-18
lines changed

01-default-static-interface-methods.md

+77-18
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
Default and Static Methods for Interfaces
22
--------
33

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
6+
(i.e. classes). Hence, promoting **[loose coupling](https://en.wikipedia.org/wiki/Loose_coupling)**.
7+
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.
512

613
> 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).
714
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.***
922

1023
```java
1124
public interface Calculator {
@@ -20,7 +33,8 @@ public interface Calculator {
2033
}
2134
```
2235

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.
2438

2539
```java
2640
public class BasicCalculator implements Calculator {
@@ -52,7 +66,9 @@ public class BasicCalculator implements Calculator {
5266

5367
## Static Factory Methods
5468

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.
5672

5773
```java
5874
Calculator calculator = new BasicCalculator();
@@ -62,17 +78,24 @@ BasicCalculator cal = new BasicCalculator();
6278
int difference = cal.subtract(3, 2);
6379
```
6480

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.
6687

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.
6890

6991
```java
7092
class BasicCalculator implements Calculator {
7193
// rest remains same
7294
}
7395
```
7496

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.
7699

77100
```java
78101
public abstract class CalculatorFactory {
@@ -83,13 +106,26 @@ public abstract class CalculatorFactory {
83106
}
84107
```
85108

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.
87111

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.
89116

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.
91126

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.
93129

94130
```java
95131
public interface Calculator {
@@ -111,7 +147,11 @@ public interface Calculator {
111147

112148
## Evolving API with time
113149

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.
115155

116156
```java
117157
public interface Calculator {
@@ -132,9 +172,21 @@ public interface Calculator {
132172
}
133173
```
134174

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`.
138190

139191
```java
140192
default void replaceAll(UnaryOperator<E> operator) {
@@ -146,7 +198,9 @@ default void replaceAll(UnaryOperator<E> operator) {
146198
}
147199
```
148200

149-
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.
150204

151205
```java
152206
default int remainder(int number, int divisor) {
@@ -156,7 +210,11 @@ default int remainder(int number, int divisor) {
156210

157211
## Multiple inheritance
158212

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:
160218

161219
**Rule 1: Methods declared in classes win over method defined in interfaces.**
162220

@@ -179,7 +237,8 @@ class App implements A{
179237
}
180238
```
181239

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.
183242

184243
**Rule 2: Otherwise, the most specific interface is selected**
185244

0 commit comments

Comments
 (0)