Skip to content

Instantly share code, notes, and snippets.

@esfand
Created June 10, 2014 04:41
Show Gist options
  • Save esfand/dd79511ede7e48a0e88e to your computer and use it in GitHub Desktop.
Save esfand/dd79511ede7e48a0e88e to your computer and use it in GitHub Desktop.

Emulating "self types" using Java Generics to simplify fluent API implementation

http://passion.forco.de/content/emulating-self-types-using-java-generics-simplif...

The Java programming language does not support the notion of "self types", that is "type of this". When implementing fluent APIs, this lack of support can lead to significant duplication of boilerplate code. Taking FEST Assertions as an example, this article shows how "self types" can be emulated in Java using Generics.

Why bother?

FEST Assertions provide a beautiful API to write assertions in Java code:

Collection

assertThat() acts as an overloaded factory for Assertion objects of different type. There are roughly 34 XxxAssert classes in FEST-Assert 1.x at the time of writing. Each of these classes implement a number of assertion methods, which check whether the actual value myItems satisfies the condition indicated by the method's name, like isNotNull or contains. If the check fails, the methods throw an AssertionError, otherwise they return this to allow chaining of method calls in a fluent manner.

Let's take CollectionAssert as an example. It provides both isNotNull() and contains(). The relevant method signatures look like this:

public class CollectionAssert /* ... */ { 

    @Override 
    public CollectionAssert isNotNull() { 
        assertNotNull(); 
        return this; 
    }

    @Override 
    public CollectionAssert contains(Object... objects) { 
        assertContains(objects); 
        return this; 
    }
}

You might ask why isNotNull() is implemented in class CollectionAssert, and not in some more generic superclass? If it's in CollectionAssert, is it also in all the other concrete assertion classes? Bad news is: yes, it is.

Return type is vital for access to fluent API methods

Of course, there actually is a superclass which might be a candidate to move the implementation of isNotNull() into, it's called GenericAssert. In it, we find:

public abstract class GenericAssert
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment