I want to compose two codecs (code below) together, so they must have compatible types to fit together. The code works but I had to use the line Codec<F,T> c = this;
for it to work otherwise the compiler didn't seem to understand correctly the type parameters (and restrictions on codec2
). I'm glad the code compiles but is there a cleaner way to achieve this?
/**
* Represents a coder-decoder from a format F to a format T
*/
public interface Codec <F,T> {
T encode(F obj);
F decode(T obj);
/**
* Compose two codecs with types <F,T> and <T,E> to a codec with type <F,E>.
* @param codec2 The second codec
* @return the new codec
*/
public default <E> Codec<F,E> compose(Codec<T,E> codec2) {
Codec<F,T> c = this;
return new Codec<F,E>() {
public E encode(F obj) { return codec2.encode(c.encode(obj)); }
public F decode(E obj) { return c.decode(codec2.decode(obj)); }
};
}
}
You're declaring an anonymous inner class that implements the Codec
interface.
return new Codec<F,E>() {
public E encode(F obj) { return codec2.encode(c.encode(obj)); }
public F decode(E obj) { return c.decode(codec2.decode(obj)); }
};
Within the body of that anonymous class declaration, this
refers to the instance of this anonymous inner class, ie. of type Codec<F, E>
.
Use Codec.this
to refer to the instance of the enclosing class (the interface in this case).
public E encode(F obj) {
return codec2.encode(Codec.this.encode(obj));
}
public F decode(E obj) {
return Codec.this.decode(codec2.decode(obj));
}