Friday, August 15, 2014

Java 8 Mixin

Java 8 introduced default interface methods. These allow an interface to provide a "default" implementation of a given method.  The default methods are used in Java 8 to add new behaviors to collections (mostly around streams) without breaking existing implementations.

Default methods also open Java to the type of language construct known as a mixin (ruby) or trait (scala).  This blog post illustrates using default methods to add comparison behavior in a class.

Problem to solve...

Java has a cumbersome API used to compare objects.  The compareTo method returns an integer whose value and sign defines if the objects are less than, equal to or greater than each other.  I want to improve this by defining a interface that has default implementations of isLessThan, isGreaterThan and isEqualTo mixin methods.  I want to be able to simply take a class that already implements Comparable and change the interface it implements to one with these new default methods. 

To demonstrate this concept I'm going to use a Zombie domain class.  The type of  a zombie defines how it compares to other zombies.  The hierarchy is as follows: Walkers are less than Runners, which are less than Fatties, which are less than Abominations (nod to Zombicide).

This first version of the Zombie class implements the Comparable interface and implements the corresponding compareTo method.  The test for the class ensures the compareTo method works based on the integer and sign returned from the method.


Solution...

This test illustrates the issue I want to fix.  To determine if one zombie is bigger than another I need to check the returned value.  This makes the code difficult to read especially for developers not familiar with the compareTo function.  It is not a fluent API.  I can improve this using an interface with some default methods.

This interface will add the methods I am looking for to my Zombie class - it could add these methods to any class that already implements Comparable. The technique used here is that I am referencing a method that the class already has - compareTo, and expanding how it can be used.

The final listing shows that Zombie now implements Compares, and no additional changes.  The tests now use the new isLessThan, isGreaterThan and isEqualTo default methods.

Wrap-up

Default methods add another technique you can use to mange cross cutting behaviors in your classes.  At first glance they seem to be a hack used by the API designers to extend the old Java APIs.  I think they are solid addition to the language.

No comments:

Post a Comment