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