{"id":1351,"date":"2012-07-15T11:18:44","date_gmt":"2012-07-15T09:18:44","guid":{"rendered":"http:\/\/doanduyhai.wordpress.com\/?p=1351"},"modified":"2012-07-15T11:18:44","modified_gmt":"2012-07-15T09:18:44","slug":"java-8-lambda-in-details-part-iv-multiple-inheritance-resolution-for-defender-methods","status":"publish","type":"post","link":"https:\/\/www.doanduyhai.com\/blog\/?p=1351","title":{"rendered":"Java 8 Lambda in details part IV : Multiple inheritance resolution for defender methods"},"content":{"rendered":"<p>In this post we&#8217;ll look at conflict resolution rules for multiple inheritance introduced along with defender methods in JDK 8.<\/p>\n<p><!--more--><\/p>\n<blockquote><p><strong>DISCLAIMER: all the details exposed in this post were observed related to the JDK 8 demo version as of <font size=\"3\" color=\"red\">July 10th 2012<\/font>. Since the JDK is still in beta, some assertions may not hold in future<\/strong>\n<\/p><\/blockquote>\n<blockquote><p> Please note that all the example code in this post can be found on my GitHub repository <a href=\"https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details\" title=\"Java8_Lambda_In_Details\" target=\"_blank\">https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details<\/a><\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<h1>I Method lookup rules<\/h1>\n<p> With JDK 8 now we can provide a default implementation for declared abstract methods in an interface, a <strong>defender method<\/strong>.<\/p>\n<p> Since it is possible for a class to implement multiple interfaces it will lead de-facto to the possibility of multiple inheritance if more than 2 interfaces in the hierarchy are providing default implementation for the same abstract method.<\/p>\n<p><strong> Please note that unlike a real multiple inheritance, defender method multiple inheritance is only behavioral, no state (field) is inherited.<\/strong> <\/p>\n<p> Below are the rules to lookup method implementation:<\/p>\n<p>1) First search for this method in the <strong>class (not interface) hierarchy <\/strong>from the current class up to the root Object class. <\/p>\n<p>1a) If a matching <strong>non abstract<\/strong> method is found, use it (<em>even if matching defender methods are found<\/em>). <\/p>\n<p><a href=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_nonabstractmethodinhierarchy.png\"><img loading=\"lazy\" src=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_nonabstractmethodinhierarchy.png\" alt=\"Lambda_Defender_Inheritance_NonAbstractMethodInHierarchy\" title=\"Lambda_Defender_Inheritance_NonAbstractMethodInHierarchy\" width=\"350\" height=\"461\" class=\"aligncenter size-full wp-image-1450\" srcset=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_nonabstractmethodinhierarchy.png 350w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_nonabstractmethodinhierarchy-228x300.png 228w\" sizes=\"(max-width: 350px) 100vw, 350px\" \/><\/a><\/p>\n<p>1b) If a matching <strong>abstract<\/strong> class is found then force the current class to implement it (<em>even if a matching defender method can be found in the hierarchy<\/em>) otherwise compilation error. <\/p>\n<p><a href=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_abstractmethodinhierarchy.png\"><img loading=\"lazy\" src=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_abstractmethodinhierarchy.png\" alt=\"Lambda_Defender_Inheritance_AbstractMethodInHierarchy\" title=\"Lambda_Defender_Inheritance_AbstractMethodInHierarchy\" width=\"350\" height=\"461\" class=\"aligncenter size-full wp-image-1452\" srcset=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_abstractmethodinhierarchy.png 350w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_abstractmethodinhierarchy-228x300.png 228w\" sizes=\"(max-width: 350px) 100vw, 350px\" \/><\/a><\/p>\n<p>The general rule of thumb is: <strong>method definition from class hierarchy, abstract or not, has priority over defender methods.<\/strong><\/p>\n<p>2) If no matching method is found in the class hierarchy, examine the interface hierarchy. Prune all the branches and only take &#8220;leaf&#8221; interfaces in the tree.<\/p>\n<p><a href=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_interfacehierarchy.png\"><img loading=\"lazy\" src=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_interfacehierarchy.png\" alt=\"\" title=\"Lambda_Defender_Inheritance_InterfaceHierarchy\" width=\"501\" height=\"341\" class=\"aligncenter size-full wp-image-1454\" srcset=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_interfacehierarchy.png 501w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_interfacehierarchy-300x204.png 300w\" sizes=\"(max-width: 501px) 100vw, 501px\" \/><\/a><\/p>\n<p>2a) If a matching defender method is found in only one of those &#8220;leaf&#8221; interfaces, use it<\/p>\n<p>2b) If more than one &#8220;leaf&#8221; interfaces provide defender methods, raise a compilation error to force the user to explicitely define the defender method to be used.<\/p>\n<p> The above rules are simplifications from the more formal rules defined in <a href=\"http:\/\/cr.openjdk.java.net\/~briangoetz\/lambda\/Defender%20Methods%20v4.pdf\" title=\"http:\/\/cr.openjdk.java.net\/~briangoetz\/lambda\/Defender%20Methods%20v4.pdf\" target=\"_blank\">http:\/\/cr.openjdk.java.net\/~briangoetz\/lambda\/Defender%20Methods%20v4.pdf<\/a><\/p>\n<p>&nbsp;<\/p>\n<h1>II Resolution examples<\/h1>\n<p>In this chapter, we present some concrete example of method resolution<\/p>\n<h3>A From SuperInterface<\/h3>\n<p> In this scenario, the method implementation comes from a defender method defined in a SuperInterface<\/p>\n<p><a href=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_fromsuperinterface1.png\"><img loading=\"lazy\" src=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_fromsuperinterface1.png\" alt=\"\" title=\"Lambda_Defender_Inheritance_FromSuperInterface\" width=\"301\" height=\"300\" class=\"aligncenter size-full wp-image-1464\" srcset=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_fromsuperinterface1.png 301w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_fromsuperinterface1-150x150.png 150w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_fromsuperinterface1-300x299.png 300w\" sizes=\"(max-width: 301px) 100vw, 301px\" \/><\/a><\/p>\n<blockquote><p> The above scenario can be illustrated by a code example on GitHub at <a href=\"https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details\" title=\"https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details\" target=\"_blank\">https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details<\/a>. Just execute the <strong>SameSuperDefenderMethod.bat<\/strong>(<strong>SameSuperDefenderMethod.sh<\/strong>) script<\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<h3>B From most specific interface<\/h3>\n<p>In this scenario, the method implementation comes from the defender method of the most specific inherited interface.<\/p>\n<p><a href=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_frommostspecificinterface1.png\"><img loading=\"lazy\" src=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_frommostspecificinterface1.png\" alt=\"Lambda_Defender_Inheritance_FromMostSpecificInterface\" title=\"Lambda_Defender_Inheritance_FromMostSpecificInterface\" width=\"301\" height=\"300\" class=\"aligncenter size-full wp-image-1469\" srcset=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_frommostspecificinterface1.png 301w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_frommostspecificinterface1-150x150.png 150w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_frommostspecificinterface1-300x299.png 300w\" sizes=\"(max-width: 301px) 100vw, 301px\" \/><\/a><\/p>\n<blockquote><p> The above scenario can be illustrated by a code example on GitHub at <a href=\"https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details\" title=\"https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details\" target=\"_blank\">https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details<\/a>. Just execute the <strong>MostSpecificDefender.bat<\/strong>(<strong>MostSpecificDefender.sh<\/strong>) script<\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<h3>C Conflicting defenders<\/h3>\n<p> When there are more than one matching defender method from &#8220;leaf&#8221; interfaces, we have a conflict and compilation issue<\/p>\n<p><a href=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_conflictingdefenders.png\"><img loading=\"lazy\" src=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_conflictingdefenders.png\" alt=\"Lambda_Defender_Inheritance_ConflictingDefenders\" title=\"Lambda_Defender_Inheritance_ConflictingDefenders\" width=\"301\" height=\"300\" class=\"aligncenter size-full wp-image-1470\" srcset=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_conflictingdefenders.png 301w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_conflictingdefenders-150x150.png 150w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_conflictingdefenders-300x299.png 300w\" sizes=\"(max-width: 301px) 100vw, 301px\" \/><\/a><\/p>\n<blockquote><p> The above scenario can be illustrated by a code example on GitHub at <a href=\"https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details\" title=\"https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details\" target=\"_blank\">https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details<\/a>. Just execute the <strong>ConflictingDefenders.bat<\/strong>(<strong>ConflictingDefenders.sh<\/strong>) script<\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<h3>D Priority to class hierarchy<\/h3>\n<p> It a matching method is found in the class hierarchy, be it abstract, then it prevails over all defender methods.<\/p>\n<p><a href=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_prioritytoclasshierarchy.png\"><img loading=\"lazy\" src=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_prioritytoclasshierarchy.png\" alt=\"Lambda_Defender_Inheritance_PriorityToClassHierarchy\" title=\"Lambda_Defender_Inheritance_PriorityToClassHierarchy\" width=\"341\" height=\"180\" class=\"aligncenter size-full wp-image-1472\" srcset=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_prioritytoclasshierarchy.png 341w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_prioritytoclasshierarchy-300x158.png 300w\" sizes=\"(max-width: 341px) 100vw, 341px\" \/><\/a><\/p>\n<blockquote><p> The above scenario can be illustrated by a code example on GitHub at <a href=\"https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details\" title=\"https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details\" target=\"_blank\">https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details<\/a>. Just execute the <strong>PriorityToHierarchy.bat<\/strong>(<strong>PriorityToHierarchy.sh<\/strong>) script<\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<h3>E Removed defender<\/h3>\n<p> Sometimes, an interface can &#8220;<strong>remove<\/strong>&#8221; the default implementation provided by one of its superinterfaces. Removal is done simply by overriding the defander method without providing any default implementation<\/p>\n<pre class=\"brush: java; highlight: [11]; title: ; wrap-lines: false; notranslate\" title=\"\">\npublic interface SuperDefender\n{\n\tString changeInput(String input) default\n\t{\n\t\treturn input.trim();\n\t}\n}\n\npublic interface RemovedDefenderInterface extends SuperDefender\n{\n\tString changeInput(String input); \/\/ Default removed here\n}\t\n<\/pre>\n<p> In such case the class implementing the interface needs to override the method.<\/p>\n<p><a href=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_removeddefenderinterface.png\"><img loading=\"lazy\" src=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_removeddefenderinterface.png\" alt=\"Lambda_Defender_Inheritance_RemovedDefenderInterface\" title=\"Lambda_Defender_Inheritance_RemovedDefenderInterface\" width=\"261\" height=\"300\" class=\"aligncenter size-full wp-image-1477\" \/><\/a><\/p>\n<blockquote><p> The above scenario can be illustrated by a code example on GitHub at <a href=\"https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details\" title=\"https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details\" target=\"_blank\">https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details<\/a>. Just execute the <strong>RemovedDefender.bat<\/strong>(<strong>RemovedDefender.sh<\/strong>) script<\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<h3>F Resolving defender conflics at interface level<\/h3>\n<p> Whenever a conflict occurs for a defender method inheritance at interface level, we can resolve it by specifying the version of the defender to be used.<\/p>\n<p><a href=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_resolveddefenderconflictatinterface.png\"><img loading=\"lazy\" src=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_resolveddefenderconflictatinterface.png\" alt=\"Lambda_Defender_Inheritance_ResolvedDefenderConflictAtInterface\" title=\"Lambda_Defender_Inheritance_ResolvedDefenderConflictAtInterface\" width=\"541\" height=\"321\" class=\"aligncenter size-full wp-image-1479\" srcset=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_resolveddefenderconflictatinterface.png 541w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2012\/07\/lambda_defender_inheritance_resolveddefenderconflictatinterface-300x178.png 300w\" sizes=\"(max-width: 541px) 100vw, 541px\" \/><\/a><\/p>\n<pre class=\"brush: java; highlight: [5]; title: ; wrap-lines: false; notranslate\" title=\"\">\npublic interface ResolvedDefenderConflictInterface extends Defender1, Defender2\n{\n\tString changeInput(String input) default\n\t{\n\t\treturn Defender2.super.changeInput(input);\n\t}\n}\n<\/pre>\n<p> Please notice the introduction of the new syntax for the <strong>super<\/strong> keyword. With JDK 8 you can prefix it with the concrete interface to be used as &#8220;parent&#8221;.<\/p>\n<blockquote><p> The above scenario can be illustrated by a code example on GitHub at <a href=\"https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details\" title=\"https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details\" target=\"_blank\">https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details<\/a>. Just execute the <strong>ResolvedDefenderConflictsAtInterface.bat<\/strong>(<strong>ResolvedDefenderConflictsAtInterface.sh<\/strong>) script<\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<h3>G Resolving defender conflics at class level<\/h3>\n<p> Similarly the resolution for defender method conflict can be done at implementing class level.<\/p>\n<pre class=\"brush: java; highlight: [5]; title: ; wrap-lines: false; notranslate\" title=\"\">\npublic class ResolvedDefenderConflictsAtClass implements Defender1, Defender2\n{\n\tpublic String changeInput(String input)\n\t{\n\t\treturn Defender1.super.changeInput(input);\n\t}\n\t...\n\t...\n}\n<\/pre>\n<p>The syntax for indicating which super interface to be used is the same (<strong>line 5<\/strong>).<\/p>\n<blockquote><p> The above scenario can be illustrated by a code example on GitHub at <a href=\"https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details\" title=\"https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details\" target=\"_blank\">https:\/\/github.com\/doanduyhai\/Java8_Lambda_In_Details<\/a>. Just execute the <strong>ResolvedDefenderConflictsAtClass.bat<\/strong>(<strong>ResolvedDefenderConflictsAtClass.sh<\/strong>) script<\/p><\/blockquote>\n<p>To be continued &#8230;<br \/>\n&nbsp;<br \/>\n&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post we&#8217;ll look at conflict resolution rules for multiple inheritance introduced along with defender methods in JDK 8.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[6,8],"tags":[],"_links":{"self":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1351"}],"collection":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1351"}],"version-history":[{"count":0,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1351\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1351"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1351"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1351"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}