From b7f6e842ae6e51443bb9f6254cf284848d563bd2 Mon Sep 17 00:00:00 2001 From: Blake Hawkins Date: Wed, 27 Apr 2016 11:38:57 +0100 Subject: [PATCH] improve grammar in section 1 --- 01-default-static-interface-methods.md | 116 +++++++++++++------------ 1 file changed, 59 insertions(+), 57 deletions(-) diff --git a/01-default-static-interface-methods.md b/01-default-static-interface-methods.md index f7b70ef..a62dd50 100644 --- a/01-default-static-interface-methods.md +++ b/01-default-static-interface-methods.md @@ -1,24 +1,24 @@ Default and Static Methods for Interfaces -------- -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)**. +We all understand that we should code to interfaces. Interfaces give the client +a contract which they should use without relying on 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 +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. +effective APIs for your libraries and applications. > 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). 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 +new methods to the API. Once an API is published, it becomes difficult 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.*** +point clear, suppose you are building a simple `Calculator` API that supports +`add`,`subtract`, `divide`, and `multiply` operations. We can write a +`Calculator` interface, as shown below. ***To keep things simple we will use +`int`.*** ```java public interface Calculator { @@ -33,8 +33,8 @@ public interface Calculator { } ``` -To back this `Calculator` interface you created a `BasicCalculator` -implementation as shown below. +To back this `Calculator` interface, you created a `BasicCalculator` +implementation, as shown below. ```java public class BasicCalculator implements Calculator { @@ -66,9 +66,9 @@ public class BasicCalculator implements Calculator { ## Static Factory Methods -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. +Suppose the 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 that shown below. ```java Calculator calculator = new BasicCalculator(); @@ -78,10 +78,10 @@ BasicCalculator cal = new BasicCalculator(); int difference = cal.subtract(3, 2); ``` -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 +Oh no! Users of the API are not coding to `Calculator` interface -- instead, +they are coding to its implementation. Your API didn't enforce 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. @@ -94,7 +94,7 @@ class BasicCalculator implements Calculator { } ``` -Next, we will write a factory class that will give us the `Calculator` instance +Next, we will write a factory class that will give us the `Calculator` instance, as shown below. ```java @@ -106,23 +106,23 @@ public abstract class CalculatorFactory { } ``` -Now, users will be forced to code to `Calculator` interface and they will not -have access to implementation details. +Now, users will be forced to code to the `Calculator` interface, and they will +not have access to implementation details. -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 +Although we have achieved our goal, we have increased the surface area of our +API by adding the 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. -**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. +**Java 8 allows you to declare static methods inside an interface**. This allows +API designers to define static utility methods like `getInstance` in the +interface itself, hence keeping the 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, the `Collections` class is a helper class +that defines various helper methods to work with Collection and its associated +interfaces. The methods defined in the `Collections` class could easily be added +to `Collection` or any of its child interfaces. The above code can be improved in Java 8 by adding a static `getInstance` method in the `Calculator` interface itself. @@ -148,10 +148,10 @@ public interface Calculator { ## Evolving API with time Some of the consumers decided to either extend the `Calculator` API by adding -methods like `remainder` or write their own implementation of `Calculator` +methods like `remainder`, or write their own implementation of the `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. +like to have a `remainder` method added to the `Calculator` interface. It looked +a very simple API change, so you added one more method to the API. ```java public interface Calculator { @@ -174,19 +174,20 @@ public interface Calculator { 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. +implementation for the `remainder` method, otherwise their code would not +compile. This is a big problem for API designers, as it makes APIs difficult to +evolve. Prior to Java 8, it was not possible to have method implementations +inside interfaces. This often became a problem when it was required to extend an +API, i.e. adding one or more methods to the interface definition. 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`. +**default**, or **defender** methods. The class implementing the interface is not +required to provide an implementation of these methods. If an implementing class +provides the implementation, then the implementing class method implementation +will be used -- otherwise the default implementation will be used. The `List` +interface has a few default methods defined, like `replaceAll`, `sort`, and +`splitIterator`. ```java default void replaceAll(UnaryOperator operator) { @@ -198,9 +199,9 @@ default void replaceAll(UnaryOperator operator) { } ``` -We can solve our API problem by defining a default method as shown below. +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. +`remainder` is defined using the `subtract`, `multiply`, and `divide` methods. ```java default int remainder(int number, int divisor) { @@ -210,13 +211,13 @@ default int remainder(int number, int divisor) { ## Multiple inheritance -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: +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 the +type level, but now it also has multiple inheritance at the behavior level. +There are three resolution rules that help decide which method will be picked: -**Rule 1: Methods declared in classes win over method defined in interfaces.** +**Rule 1: Methods declared in classes win over methods defined in interfaces.** ```java interface A { @@ -237,8 +238,8 @@ class App implements A{ } ``` -This will print `inside App` as methods declared in class have precedence over -methods declared in interfaces. +This will print `inside App`, as methods declared in the implementing class have +precedence over methods declared in interfaces. **Rule 2: Otherwise, the most specific interface is selected** @@ -264,7 +265,8 @@ class App implements C, B, A { This will print `inside C`. -**Rule 3: Otherwise, class has to call the desired implementation explicitly** +**Rule 3: Otherwise, the class has to call the desired implementation +unambiguously** ```java interface A {