JaroslavTulach at 05:59, 22 December 2021 - 2021-12-22 05:59:54

←Older revision Revision as of 05:59, 22 December 2021
Line 1: Line 1:
[[DefaultMethods]] is a new feature of [[JDK]]8. It allows one to specify ('''default''') implementation of [[Java]] '''interface''' method.
[[DefaultMethods]] is a new feature of [[JDK]]8. It allows one to specify ('''default''') implementation of [[Java]] '''interface''' method.
-
Adding methods with some implementation breaks the clear separation between [[Java]] '''interface''' (used to specify a contract only) and '''class''' (provides some implementation). Many members of the [[Java]] community were crying for having a way to add methods into already published '''interface''' in a [[BackwardCompatibility|backward compatible]] way for ages. Of course, as usual in [[Java]], only when the [[JDK]] team felt the need itself (because of adding a lot of new [[Lambda]] methods into {{JDK|java/util|Collection}} & co. classes), it listened to the general request.
+
Adding methods with some implementation breaks the clear separation between [[Java]] '''interface''' (used to specify a contract only) and '''class''' (provides some implementation). Many members of the [[Java]] community were crying for having a way to add methods into already published '''interface''' in a [[BackwardCompatibility|backward compatible]] way for ages. Of course, as usual in [[Java]], only when the [[JDK]] team felt the need itself (because of adding a lot of new [[Lambda]] methods into {{JDK|java/util|Collection}} & co. classes), it became [[pragmatic]] and listened to the general request.
On the other hand, there were people claiming that [[DefaultMethods]] are bad - that an interface should be a code-less specification and the change would have consequences. And yes, it does. This page describes some of them.
On the other hand, there were people claiming that [[DefaultMethods]] are bad - that an interface should be a code-less specification and the change would have consequences. And yes, it does. This page describes some of them.

JaroslavTulach at 04:44, 1 October 2021 - 2021-10-01 04:44:51

←Older revision Revision as of 04:44, 1 October 2021
Line 15: Line 15:
== By-Passing Your Interface ==
== By-Passing Your Interface ==
-
When I was implementing [[netbeans:Html4Java]] [[API]], I had to create an ''observable list'' - so I did it and created [http://hg.netbeans.org/html4j/file/a973ef098049/json/src/main/java/org/netbeans/html/json/impl/JSONList.java#l57 JSONList]. I've carefully overwritten each '''public''' method that modified the list state and called a change notification handler. What could go wrong?
+
When I was implementing [[Html4Java]] [[API]], I had to create an ''observable list'' - so I did it and created [http://hg.netbeans.org/html4j/file/a973ef098049/json/src/main/java/org/netbeans/html/json/impl/JSONList.java#l57 JSONList]. I've carefully overwritten each '''public''' method that modified the list state and called a change notification handler. What could go wrong?
<source lang="java">
<source lang="java">

JaroslavTulach: /* Can you disagree? */ - 2020-09-28 06:03:01

Can you disagree?

←Older revision Revision as of 06:03, 28 September 2020
Line 88: Line 88:
Then it is [[clarity|clear]]: Use '''final''' classes to represent [[ClientAPI]] types and use ''pure'' '''interface''' to represent [[ProviderAPI]]. There is no place for [[default methods]] in this ideal setup... but of course, we are humans, so we always find excuses for using/doing what we like, right?
Then it is [[clarity|clear]]: Use '''final''' classes to represent [[ClientAPI]] types and use ''pure'' '''interface''' to represent [[ProviderAPI]]. There is no place for [[default methods]] in this ideal setup... but of course, we are humans, so we always find excuses for using/doing what we like, right?
 +
 +
== [[BinaryIncompatibleDefaultMethods|Even Binary Incompatible]] ==
 +
 +
{{:BinaryIncompatibleDefaultMethods}}
== Dušan can: [[Default Listener Methods]] ==
== Dušan can: [[Default Listener Methods]] ==

JaroslavTulach: /* Useful? */ - 2019-02-07 11:06:10

Useful?

←Older revision Revision as of 11:06, 7 February 2019
Line 9: Line 9:
From one point of view, it is a useful concept. Especially if one paints himself into a corner by not following advices of [[TheAPIBook]] when designing the first version of the [[API]]. If one mixes [[APIvsSPI|client and provider]] [[API]] into one type - like {{JDK|java/util|List}}, then one gets into trouble. On one side people call into the type (e.g. use it as [[ClientAPI]]). On the other hand, there are people who implement it - e.g. use the {{JDK|java/util|List}} type as a [[ProviderAPI]]. They create standard classes like {{JDK|java/util|ArrayList}}, but also numerous custom implementations written by developers around the globe.
From one point of view, it is a useful concept. Especially if one paints himself into a corner by not following advices of [[TheAPIBook]] when designing the first version of the [[API]]. If one mixes [[APIvsSPI|client and provider]] [[API]] into one type - like {{JDK|java/util|List}}, then one gets into trouble. On one side people call into the type (e.g. use it as [[ClientAPI]]). On the other hand, there are people who implement it - e.g. use the {{JDK|java/util|List}} type as a [[ProviderAPI]]. They create standard classes like {{JDK|java/util|ArrayList}}, but also numerous custom implementations written by developers around the globe.
-
Later an [[evolution]] of the [[API] may require one to add new methods into the [[ClientAPI]] side of the contract. In such situation one is going to welcome [[default methods]] as a nice way to get ''out of the corner''. By adding [[default methods]] one can enhance the [[ClientAPI]] part of the interface, while keeping (most of) the compatibility for those who implement the '''interface'''.
+
Later an [[evolution]] of the [[API]] may require one to add new methods into the [[ClientAPI]] side of the contract. In such situation one is going to welcome [[default methods]] as a nice way to get ''out of the corner''. By adding [[default methods]] one can enhance the [[ClientAPI]] part of the interface, while keeping (most of) the compatibility for those who implement the '''interface'''.
However the concept of [[default methods]] also comes with drawbacks.
However the concept of [[default methods]] also comes with drawbacks.

JaroslavTulach: /* Default Listener Methods */ - 2018-04-19 06:44:06

Default Listener Methods

←Older revision Revision as of 06:44, 19 April 2018
Line 89: Line 89:
Then it is [[clarity|clear]]: Use '''final''' classes to represent [[ClientAPI]] types and use ''pure'' '''interface''' to represent [[ProviderAPI]]. There is no place for [[default methods]] in this ideal setup... but of course, we are humans, so we always find excuses for using/doing what we like, right?
Then it is [[clarity|clear]]: Use '''final''' classes to represent [[ClientAPI]] types and use ''pure'' '''interface''' to represent [[ProviderAPI]]. There is no place for [[default methods]] in this ideal setup... but of course, we are humans, so we always find excuses for using/doing what we like, right?
-
=== [[Default Listener Methods]] ===
+
== Dušan can: [[Default Listener Methods]] ==
{{:Default Listener Methods}}
{{:Default Listener Methods}}
[[Category:APIDesignPatterns:Anti]] [[Category:APIDesignPatterns:Clarity]] [[Category:APIDesignPatterns:Evolution]]
[[Category:APIDesignPatterns:Anti]] [[Category:APIDesignPatterns:Clarity]] [[Category:APIDesignPatterns:Evolution]]

JaroslavTulach: /* Default Listener Methods */ - 2018-04-19 06:28:07

Default Listener Methods

←Older revision Revision as of 06:28, 19 April 2018
Line 89: Line 89:
Then it is [[clarity|clear]]: Use '''final''' classes to represent [[ClientAPI]] types and use ''pure'' '''interface''' to represent [[ProviderAPI]]. There is no place for [[default methods]] in this ideal setup... but of course, we are humans, so we always find excuses for using/doing what we like, right?
Then it is [[clarity|clear]]: Use '''final''' classes to represent [[ClientAPI]] types and use ''pure'' '''interface''' to represent [[ProviderAPI]]. There is no place for [[default methods]] in this ideal setup... but of course, we are humans, so we always find excuses for using/doing what we like, right?
-
=== Default Listener Methods ===
+
=== [[Default Listener Methods]] ===
-
 
+
-
Recently I tried to apply the here-in described knowledge to work done my colleagues and they (obviously) objected. That's OK, that happens all the time, but the worst thing is: they were right! Do you remember the classical [[JavaBean]] pattern called ''listener'' and its associated ''adapter''? Imagine for example {{JDK|java/awt/event|MouseListener}} and {{JDK|java/awt/event|MouseAdapter}}. The pair of classes was created to save users from always implementing all the ''listener'' methods and rather use the adapter. Turns out [[DefaultMethods]] allow us to merge these two classes into one:
+
-
 
+
-
<source lang="java">
+
-
public interface MouseListener extends EventListener {
+
-
public default void mouseClicked(MouseEvent e) {}
+
-
public default void mousePressed(MouseEvent e) {}
+
-
public default void mouseReleased(MouseEvent e) {}
+
-
public default void mouseEntered(MouseEvent e) {}
+
-
public default void mouseExited(MouseEvent e) {}
+
-
}
+
-
</source>
+
-
 
+
-
Such listener type is both a ''listener'' as well as an ''adaptor'' and there is nothing wrong with that! Why does the above philippic against using [[DefaultMethods]] in an [[API]] doesn't apply? The code that runs after one of the listener methods isn't (unless an unexpected [[exception]] happens) influenced by the code in the method - e.g. it shouldn't matter what the method does and thus adding new method with default empty implementation seems to be OK. The necessary condition for that is the fact that the methods return '''void''' - if they returned anything observable - e.g. the default body would something like:
+
-
 
+
-
<source lang="java">
+
-
/** @return true to "consume" the event */
+
-
public default boolean mouseExited(MouseEvent e) {
+
-
return false;
+
-
}
+
-
</source>
+
-
 
+
-
then all the above arguments against these methods would apply again, as it would be impossible to distinguish between methods having default implementation or methods overridden with intention to keep the default implementation.
+
-
 
+
-
Thanks Dušane for pointing the ''listener'' case out! As mentioned in [[TheAPIBook]], slight change in the initial situation may turn the final advice up side down. Thus I gladly (have to) admit: using [[DefaultMethods]] in listener [[JavaBean]] pattern is perfectly fine.
+
 +
{{:Default Listener Methods}}
[[Category:APIDesignPatterns:Anti]] [[Category:APIDesignPatterns:Clarity]] [[Category:APIDesignPatterns:Evolution]]
[[Category:APIDesignPatterns:Anti]] [[Category:APIDesignPatterns:Clarity]] [[Category:APIDesignPatterns:Evolution]]

JaroslavTulach: /* Can you disagree? */ - 2018-04-19 06:27:21

Can you disagree?

←Older revision Revision as of 06:27, 19 April 2018
Line 88: Line 88:
Then it is [[clarity|clear]]: Use '''final''' classes to represent [[ClientAPI]] types and use ''pure'' '''interface''' to represent [[ProviderAPI]]. There is no place for [[default methods]] in this ideal setup... but of course, we are humans, so we always find excuses for using/doing what we like, right?
Then it is [[clarity|clear]]: Use '''final''' classes to represent [[ClientAPI]] types and use ''pure'' '''interface''' to represent [[ProviderAPI]]. There is no place for [[default methods]] in this ideal setup... but of course, we are humans, so we always find excuses for using/doing what we like, right?
 +
 +
=== Default Listener Methods ===
 +
 +
Recently I tried to apply the here-in described knowledge to work done my colleagues and they (obviously) objected. That's OK, that happens all the time, but the worst thing is: they were right! Do you remember the classical [[JavaBean]] pattern called ''listener'' and its associated ''adapter''? Imagine for example {{JDK|java/awt/event|MouseListener}} and {{JDK|java/awt/event|MouseAdapter}}. The pair of classes was created to save users from always implementing all the ''listener'' methods and rather use the adapter. Turns out [[DefaultMethods]] allow us to merge these two classes into one:
 +
 +
<source lang="java">
 +
public interface MouseListener extends EventListener {
 +
public default void mouseClicked(MouseEvent e) {}
 +
public default void mousePressed(MouseEvent e) {}
 +
public default void mouseReleased(MouseEvent e) {}
 +
public default void mouseEntered(MouseEvent e) {}
 +
public default void mouseExited(MouseEvent e) {}
 +
}
 +
</source>
 +
 +
Such listener type is both a ''listener'' as well as an ''adaptor'' and there is nothing wrong with that! Why does the above philippic against using [[DefaultMethods]] in an [[API]] doesn't apply? The code that runs after one of the listener methods isn't (unless an unexpected [[exception]] happens) influenced by the code in the method - e.g. it shouldn't matter what the method does and thus adding new method with default empty implementation seems to be OK. The necessary condition for that is the fact that the methods return '''void''' - if they returned anything observable - e.g. the default body would something like:
 +
 +
<source lang="java">
 +
/** @return true to "consume" the event */
 +
public default boolean mouseExited(MouseEvent e) {
 +
return false;
 +
}
 +
</source>
 +
 +
then all the above arguments against these methods would apply again, as it would be impossible to distinguish between methods having default implementation or methods overridden with intention to keep the default implementation.
 +
 +
Thanks Dušane for pointing the ''listener'' case out! As mentioned in [[TheAPIBook]], slight change in the initial situation may turn the final advice up side down. Thus I gladly (have to) admit: using [[DefaultMethods]] in listener [[JavaBean]] pattern is perfectly fine.
 +
[[Category:APIDesignPatterns:Anti]] [[Category:APIDesignPatterns:Clarity]] [[Category:APIDesignPatterns:Evolution]]
[[Category:APIDesignPatterns:Anti]] [[Category:APIDesignPatterns:Clarity]] [[Category:APIDesignPatterns:Evolution]]

JaroslavTulach: /* Can you disagree? */ - 2018-03-06 08:48:13

Can you disagree?

←Older revision Revision as of 08:48, 6 March 2018
Line 81: Line 81:
== Can you disagree? ==
== Can you disagree? ==
-
[[I]] also believe [[default methods]] can be useful, so [[I]] fully understand if you are hesitating to accept the above arguments. However the conclusions are inevitable from the chain of thoughts:
+
[[I]] also believe [[default methods]] can be useful, so [[I]] fully understand if you are hesitating to accept the above arguments. However the conclusions are inevitable from the following chain of thoughts:
* Do you agree that mixing [[APIvsSPI|client and provider APIs]] is causing troubles?
* Do you agree that mixing [[APIvsSPI|client and provider APIs]] is causing troubles?

JaroslavTulach: /* Can you disagree? */ - 2018-03-06 08:47:50

Can you disagree?

←Older revision Revision as of 08:47, 6 March 2018
Line 87: Line 87:
* Are you willing to search for [[ClarityOfTypes]] in the [[API]] that you design?
* Are you willing to search for [[ClarityOfTypes]] in the [[API]] that you design?
-
Then it is [[clarity|clear]]: Use '''final''' classes to represent [[ClientAPI]] types and use ''pure'' '''interface''' to represent [[ProviderAPI]]. There is no place for [[default methods]] in this setup...
+
Then it is [[clarity|clear]]: Use '''final''' classes to represent [[ClientAPI]] types and use ''pure'' '''interface''' to represent [[ProviderAPI]]. There is no place for [[default methods]] in this ideal setup... but of course, we are humans, so we always find excuses for using/doing what we like, right?
[[Category:APIDesignPatterns:Anti]] [[Category:APIDesignPatterns:Clarity]] [[Category:APIDesignPatterns:Evolution]]
[[Category:APIDesignPatterns:Anti]] [[Category:APIDesignPatterns:Clarity]] [[Category:APIDesignPatterns:Evolution]]

JaroslavTulach: /* Increasing Fuzziness */ - 2018-03-06 08:46:42

Increasing Fuzziness

←Older revision Revision as of 08:46, 6 March 2018
Line 78: Line 78:
As such [[I]] am suggesting to '''not''' use [[default methods]] when designing [[API]]. For example when designing a [[visitor]], it is better to get along without them. A [[good]] [[API]] designed with [[cluelessness]] in mind, shall avoid [[default methods]]!
As such [[I]] am suggesting to '''not''' use [[default methods]] when designing [[API]]. For example when designing a [[visitor]], it is better to get along without them. A [[good]] [[API]] designed with [[cluelessness]] in mind, shall avoid [[default methods]]!
 +
 +
== Can you disagree? ==
 +
 +
[[I]] also believe [[default methods]] can be useful, so [[I]] fully understand if you are hesitating to accept the above arguments. However the conclusions are inevitable from the chain of thoughts:
 +
 +
* Do you agree that mixing [[APIvsSPI|client and provider APIs]] is causing troubles?
 +
* Do you agree that [[clarity]] is an important aspect of an [[API]]?
 +
* Are you willing to search for [[ClarityOfTypes]] in the [[API]] that you design?
 +
 +
Then it is [[clarity|clear]]: Use '''final''' classes to represent [[ClientAPI]] types and use ''pure'' '''interface''' to represent [[ProviderAPI]]. There is no place for [[default methods]] in this setup...
[[Category:APIDesignPatterns:Anti]] [[Category:APIDesignPatterns:Clarity]] [[Category:APIDesignPatterns:Evolution]]
[[Category:APIDesignPatterns:Anti]] [[Category:APIDesignPatterns:Clarity]] [[Category:APIDesignPatterns:Evolution]]