Java: Partially applied generic classes - how to eliminate redundant type parameters?

In my Java application I created methods that returnEither<A, B>objects.

However the type I really use isEither<String, T>, i.e.Stringis always the left type parameter, while the right parameter can be any type.

Here is thefunctionaljavaEitherimplementation I am using:

https://github.com/functionaljava/functionaljava/blob/master/core/src/main/java/fj/data/Either.java

HereEitheris defined as:

public abstract class Either<A, B>

To make my code less verbose, I would like to create a generic classLeftAppliedEither<T>, which will represent anEitherin which the left type parameter is set to be String.

So I guess the way to do it is:

public abstract class LeftAppliedEither<T> extends Either<String, T> {}

However this does not work.

First,Eithercannot be extended by me since its only constructor is defined asprivate.

Second, let's assume I have solved the first problem by simply copyingEither's code into my code (let's call itMyEither) and removing the private constructor (and solving some minor compilation errors).

So I have the following class in my code:

package fj.data;

//import ....

public abstract class MyEither<A, B> {
    //  private MyEither() {
    //
    //  }

    //the rest of the code is more or less like in the original Either

}

Still, I would have the following problem:

I cannot write the following code:

LeftAppliedEither<Integer> hello = LeftAppliedEither.left("hello");

I only can do things like:

MyEither<String,Integer> hello = LeftAppliedEither.left("hello");

Well, that defeats the whole reason I was making this change - I wanted not to be required to use in my code the generic type with two parameters, since specifying the leftStringis redundant.

Are there better and more elegant ways to achieve this, other than rewriting the wholeLeftAppliedEitherclass?

What you are having here is a static method:

LeftAppliedEither<Integer> hello = LeftAppliedEither.left("hello");

This static method is not affected by inheritance. As you can see in the code, it brings its own generics. So inheritance does not help you here:

/**
 * Construct a left value of either.
 * @param a The value underlying the either.
 * @return A left value of either.
 */
public static <A, B> Either<A, B> left(final A a) {
    return new Left<A, B>(a);
}

So basically what you need do is to refactor the complete either-class to replace each "A" by a String and remove all "A" in the generic-parameters as shown in this example:

/**
 * Construct a left value of either.
 * @param a The value underlying the either.
 * @return A left value of either.
 */
public static <B> MyEither<B> left(final String a) {
    return new MyLeft<B>(a);
}

Unfortunately there is not much more what you can do (except the obvious, just write the "String" each time as mentioned in the comments. It may be redundant, but it also helps you clearly to understand the code. So I fell it is useful)

Tags: java, generics