Suppose I have the following structure:
public interface A {
}
public interface B {
}
public interface B1 extends B {
}
public interface B2 extends B {
}
public class C implements A, B1 {
private final String s;
public C(final String s) {
this.s = s;
}
}
public class D implements A, B2 {
private final Exception e;
public D(final Exception e) {
this.e = e;
}
}
public class SomeClass<T> {
private final T t;
private final Exception e;
public SomeClass(final T t, final Exception e) {
this.t = t;
this.e = e;
}
public <U extends B> U transform(final java.util.function.Function<T, ? extends U> mapper1, final java.util.function.Function<Exception, ? extends U> mapper2) {
return t == null ? mapper2.apply(e) : mapper1.apply(t);
}
}
When now we do the following in another class:
public class AnotherClass {
public static void main(final String[] args) {
SomeClass<String> someClass = new SomeClass<>("Hello World!", null);
// this line is what is bothering me
A mappedResult = someClass.transform(C::new, D::new);
}
}
The code compiles without any problems. Why does the code compile? How is it possible that the type of 'mappedResult' can be A, even though the generic U in the method is declared to be a subtype of B?
Ok, so based on the comments on the question and some discussion with other people, there was a major point that I missed that might need addressing and that actually explains the answer given in the comments.
It's clear that the following compiles:
Object mappedResult = someClass.transform(C::new, D::new);
And yet Object is not a subclass of B, of course. The bound will ensure that the the types of C and D (in this case) will be a subtype of B, but they can be other types as well due thanks to other interfaces both C and D implement. The compiler will check what types they are and look at the most specific type(s) that they have in common. In this case, that is both A and B, so the type is derived to be A & B. Therefore, assigning this result to A is possible, because the compiler will derive the result to be an A as well.
The bound does provide some restrictions regarding the input, but not regarding the output and not regarding to the types of variables to which you can assign the result. That is what I was confused about before.
Another way to see this is the following: if the method had been defined as follows:
public <U> U transform(final java.util.function.Function<T, ? extends U> mapper1, final java.util.function.Function<Exception, ? extends U> mapper2) {
return t == null ? mapper2.apply(e) : mapper1.apply(t);
}
then the result can still be assigned to an A or a B when calling it as before. The bound had no influence on that. All it ensures here is that both mapper functions need to map to a result that is a subtype of U. With the bound, that becomes a subtype of U which is a subtype of B. But the fact that the result is a subtype of A doesn't change the fact that it is also a subtype of B. Therefore, the result can be assigned to either type.
I have a parent class, Parent, with two child classes, A and B. I have another class, Wrapper<Type1,Type2>, that contains an interface, Function<Type1,Type2>, which is supposed to transform an A into a B or a B into an A.
If I define
new Wrapper<A,B>(new Function<A,B>(){public B transform(A a){return new B(a);}});
outside of the Wrapper class, then this works fine.
I run into the problem that I can't instantiate a generic type when I want to define a default Function for the default constructor public Wrapper() within the Wrapper<Type1,Type2> class itself.
Eclipse recommends casting from Type1 to Type2, but the problem is that A can't cast to B because they are sibling classes. I do have constructors for Parent(Parent), A(B), and B(A), so it would be great if I could implement a generic constructor somehow. How can I work around this?
public class Parent {
protected int value = 0;
public void setValue(int x){ value = x; }
public int getValue(){ return value; }
public Parent(){}
public Parent(A a){setValue(a.getValue());}
public Parent(B b){setValue(b.getValue());}
public Parent(Parent p){setValue(p.getValue());}
}
public class A extends Parent{
public A(){ setValue(1); }
public A(B b){ setValue( b.getValue()); }
}
public class B extends Parent{
public B(){ setValue(2); }
public B(A a){ setValue(a.getValue()); }
}
public interface Function <Type1 extends Parent, Type2 extends Parent> {
public Type2 transform(Type1 t);
}
public class Wrapper<Type1 extends Parent, Type2 extends Parent> {
Function<Type1,Type2> function;
public Wrapper(Function<Type1,Type2> x){ function = x; }
public Wrapper(){
function = new Function<Type1,Type2>(){
public Type2 transform(Type1 t){
///I want to use constructor Type2(t), given that they both extend Parent
//return new Type2( t);
return (Type2) t; ///causes an error because can't cast from A to B
}
};
}
public Type2 transform(Type1 t){
return function.transform(t);
}
}
public class Main {
public static void main(String[] args){
///Start with custom function. This part works.
Wrapper<A,B> wrapper = new Wrapper<A,B>(
new Function<A,B>(){
public B transform(A a){
///Want to use constructor B(a)
///Can't cast A to B
return new B(a);
}
}
);
A a = new A();
B b = wrapper.transform(a);
///This part works
System.out.println(b.getValue());
///Next try the default Function
wrapper = new Wrapper<A,B>();
b = wrapper.transform(a); ///This part causes the error, as wrapper attempts to cast from A to B
System.out.println(b.getValue());
}
}
Edit:
My question is unique in scope and implementation from the suggested duplicate. E.g., the structure of my code is a simple parent with two sibling child classes. The structure in the possible duplicate is more intricate, involving multiple generations and child classes that are disheveled in a confusing way. I'm not sure what that code is attempting to do, and the answer didn't help me understand my own question in the slightest as it seemed particular to the distinct structure of the other question.
There's no way to make a "generic" constructor. The solution closes to your current implementation is to instantiate objects in your function. As this is anyway the responsibility of the caller (in your design), then it's easy:
Wrapper<A, B> wrapper = new Wrapper<A, B>((a) -> new B(a));
But where the default Wrapper() constructor is being called, you can make the caller send Class objects for type1 and type2:
public Wrapper(Class<Type1> type1Class, Class<Type2> type2Class) {
this.function = (object1) -> {
try {
return type2Class.getConstructor(type1Class).newInstance(object1);
} catch (Exception e) {
throw new RuntimeException(e);
}
};
}
With both of the above, your main method will look like the following:
public static void main(String... args) {
Wrapper<A, B> wrapper = new Wrapper<A, B>((a) -> new B(a));
A a = new A();
B b = wrapper.transform(a);
System.out.println(b.getValue());
wrapper = new Wrapper<A, B>(A.class, B.class);
b = wrapper.transform(a);
System.out.println(b.getValue());
}
And this runs without any type cast errors.
The java1.7 version of the above lambda expressions:
Wrapper<A, B> wrapper = new Wrapper<A, B>(new Function<A, B>() {
#Override
public B transform(A a) {
return new B(a);
}
});
And:
this.function = new Function<Type1, Type2>() {
#Override
public Type2 transform(Type1 object1) {
try {
return type2Class.getConstructor(type1Class).newInstance(object1);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
Since it's not possible to create an instance using a generic type parameter we must work around it. I'll restrict the answer to Java 7 as I read from the comments you're working with. Here is my suggestion:
public interface Transform<P extends Parent> {
P with(int value);
}
public static void main(String[] args) {
Transform<B> transformToB = new Transform<B>() {
#Override
public B with(int value) {
return new B(value);
}
};
A a = new A();
B b = transformToB.with(a.getValue());
System.out.println(b.getValue());
}
How it works?
We have an interface Transform<P extends Parent> defining the method with. This method has one parameter. This is the only one field of the classes you defined. Using this value the method has to return an instance of some P which extends Parent. Looking at the implementation of transformToB it creates a B instance by calling the (by me added) constructor B(int value).
Why another constructor?
Declaring constructors like B(A a) or A(B b) results in a circular dependency between these classes. A and B aren't loosely coupled. Declaring a constructor which takes only a value we instantiate the state without having to know where this value comes from.
Also declaring constructors like Parent(A a) and Parent(B b) introduces dependencies to Parent on it's subclasses. Following this approach Parent would need to provide a constructor for each subclass.
Possible extension:
If value is just an example for many other fields, we do not want to define a constructor like A(int value1, int value2, String value3, ...) having many parameters. Instead of we could use the default constructor A() and do the transformation like this:
interface Transform<From extends Parent, To extends Parent> {
To from(From f);
}
public static void main(String[] args) {
Transform<A, B> transformToB = new Transform<A, B>() {
#Override
public B from(A a) {
B b = new B();
b.setValue(a.getValue());
b.setValue2(a.getValue2());
b.setValue3(a.getValue3());
return b;
}
};
A a = new A();
B b = transformToB.from(a);
System.out.println(b.getValue());
}
This last approach is also applicable if A and B have different fields. In case B has a field String value4 we could add an additional line to transformToB like b.setValue4(a.getValue3()+"#"+a.getValue2());.
How can I write a typesafe Java method that returns either something of class a or something of class b? For example:
public ... either(boolean b) {
if (b) {
return new Integer(1);
} else {
return new String("hi");
}
}
What is the cleanest way?
( The only thing that comes to my mind is using exceptions which is obviously bad, as it is abusing a error-handling mechanism for a general language feature ...
public String either(boolean b) throws IntException {
if (b) {
return new String("test");
} else {
throw new IntException(new Integer(1));
}
}
)
My general formula for simulating algebraic data types is:
The type is an abstract base class, and the constructors are subclasses of that
The data for each constructor are defined in each subclass. (This allows constructors with different numbers of data to work correctly. It also removes the need to maintain invariants like only one variable is non-null or stuff like that).
The constructors of the subclasses serve to construct the value for each constructor.
To deconstruct it, one uses instanceof to check the constructor, and downcast to the appropriate type to get the data.
So for Either a b, it would be something like this:
abstract class Either<A, B> { }
class Left<A, B> extends Either<A, B> {
public A left_value;
public Left(A a) { left_value = a; }
}
class Right<A, B> extends Either<A, B> {
public B right_value;
public Right(B b) { right_value = b; }
}
// to construct it
Either<A, B> foo = new Left<A, B>(some_A_value);
Either<A, B> bar = new Right<A, B>(some_B_value);
// to deconstruct it
if (foo instanceof Left) {
Left<A, B> foo_left = (Left<A, B>)foo;
// do stuff with foo_left.a
} else if (foo instanceof Right) {
Right<A, B> foo_right = (Right<A, B>)foo;
// do stuff with foo_right.b
}
Here is a statically checked type-safe solution; this means you cannot create runtime errors. Please read the previous sentence in the way it is meant. Yes, you can provoke exceptions in some way or the other...
It's pretty verbose, but hey, it's Java!
public class Either<A,B> {
interface Function<T> {
public void apply(T x);
}
private A left = null;
private B right = null;
private Either(A a,B b) {
left = a;
right = b;
}
public static <A,B> Either<A,B> left(A a) {
return new Either<A,B>(a,null);
}
public static <A,B> Either<A,B> right(B b) {
return new Either<A,B>(null,b);
}
/* Here's the important part: */
public void fold(Function<A> ifLeft, Function<B> ifRight) {
if(right == null)
ifLeft.apply(left);
else
ifRight.apply(right);
}
public static void main(String[] args) {
Either<String,Integer> e1 = Either.left("foo");
e1.fold(
new Function<String>() {
public void apply(String x) {
System.out.println(x);
}
},
new Function<Integer>() {
public void apply(Integer x) {
System.out.println("Integer: " + x);
}
});
}
}
You might want to look at Functional Java and Tony Morris' blog.
Here is the link to the implementation of Either in Functional Java. The fold in my example is called either there. They have a more sophisticated version of fold, that is able to return a value (which seems appropriate for functional programming style).
You can have a close correspondence with Haskell by writing a generic class Either, parametric on two types L and R with two constructors (one taking in an L, and one taking in an R) and two methods L getLeft() and R getRight() such that they either return the value passed when constructing, or throw an exception.
The suggestions already provided, although feasible, are not complete as they rely on some null references and effectively make "Either" masquerade as a tuple of values. A disjoint sum is obviously one type or the other.
I'd suggest having a look at the implementation of FunctionalJava's Either as an example.
The big thing is not to try to write in one language whilst writing in another. Generally in Java you want to put the behaviour in the object, rather than having a "script" running outside with encapsulation destroyed by get methods. There is no context for making that kind of suggestion here.
One safe way of dealing with this particular little fragment is to write it as a callback. Similar to a very simple visitor.
public interface Either {
void string(String value);
void integer(int value);
}
public void either(Either handler, boolean b) throws IntException {
if (b) {
handler.string("test");
} else {
handler.integer(new Integer(1));
}
}
You may well want to implement with pure functions and return a value to the calling context.
public interface Either<R> {
R string(String value);
R integer(int value);
}
public <R> R either(Either<? extends R> handler, boolean b) throws IntException {
return b ?
handler.string("test") :
handler.integer(new Integer(1));
}
(Use Void (capital 'V') if you want to get back to being uninterested in the return value.)
I've implemented it in a Scala-like fashion in the following way. It's a little verbose (it is Java, after all :)) but it's type safe.
public interface Choice {
public enum Type {
LEFT, RIGHT
}
public Type getType();
interface Get<T> {
T value();
}
}
public abstract class Either<A, B> implements Choice {
private static class Base<A, B> extends Either<A, B> {
#Override
public Left leftValue() {
throw new UnsupportedOperationException();
}
#Override
public Right rightValue() {
throw new UnsupportedOperationException();
}
#Override
public Type getType() {
throw new UnsupportedOperationException();
}
}
public abstract Left leftValue();
public abstract Right rightValue();
public static <A, B> Either<A, B> left(A value) {
return new Base<A, B>().new Left(value);
}
public static <A, B> Either<A, B> right(B value) {
return new Base<A, B>().new Right(value);
}
public class Left extends Either<A, B> implements Get<A> {
private A value;
public Left(A value) {
this.value = value;
}
#Override
public Type getType() {
return Type.LEFT;
}
#Override
public Left leftValue() {
return Left.this;
}
#Override
public Right rightValue() {
return null;
}
#Override
public A value() {
return value;
}
}
public class Right extends Either<A, B> implements Get<B> {
private B value;
public Right(B value) {
this.value = value;
}
#Override
public Left leftValue() {
return null;
}
#Override
public Right rightValue() {
return this;
}
#Override
public Type getType() {
return Type.RIGHT;
}
#Override
public B value() {
return value;
}
}
}
Then you can pass Either<A,B> instances around on your code. The Type enum is mainly used on switch statements.
Creating Either values is simple as:
Either<A, B> underTest;
A value = new A();
underTest = Either.left(value);
assertEquals(Choice.Type.LEFT, underTest.getType());
assertSame(underTest, underTest.leftValue());
assertNull(underTest.rightValue());
assertSame(value, underTest.leftValue().value());
Or, in the typical situation where it is used instead of exceptions,
public <Error, Result> Either<Error,Result> doSomething() {
// pseudo code
if (ok) {
Result value = ...
return Either.right(value);
} else {
Error errorMsg = ...
return Either.left(errorMsg);
}
}
// somewhere in the code...
Either<Err, Res> result = doSomething();
switch(result.getType()) {
case Choice.Type.LEFT:
// Handle error
Err errorValue = result.leftValue().value();
break;
case Choice.Type.RIGHT:
// Process result
Res resultValue = result.rightValue().value();
break;
}
Hope it helps.
From http://blog.tmorris.net/posts/maybe-in-java/ I learned that you can make the outer class's constructor private so only nested classes can subclass it. This trick is just as type safe as the best above, but much less verbose, works for any ADT you want like Scala's case class.
public abstract class Either<A, B> {
private Either() { } // makes this a safe ADT
public abstract boolean isRight();
public final static class Left<L, R> extends Either<L, R> {
public final L left_value;
public Left(L l) { left_value = l; }
public boolean isRight() { return false; }
}
public final static class Right<L, R> extends Either<L, R> {
public final R right_value;
public Right(R r) { right_value = r; }
public boolean isRight() { return true; }
}
}
(started from top answer's code and style)
Note that:
The finals on the subclass are optional. Without them you can subtype Left and Right, but still not Either directly. Thus without the finals Either has limited width but unbounded depth.
With ADTs like this, I see no reason to jump on the whole anti-instanceof bandwagon. A boolean works for Maybe or Either, but in general instanceof is your best and only option.
Thanks to Derive4J algebraic data types are now very easy in Java. All you have to do is create the following class:
import java.util.function.Function;
#Data
public abstract class Either<A, B> {
Either(){}
/**
* The catamorphism for either. Folds over this either breaking into left or right.
*
* #param left The function to call if this is left.
* #param right The function to call if this is right.
* #return The reduced value.
*/
public abstract <X> X either(Function<A, X> left, Function<B, X> right);
}
And Derive4J will take care of creating constructors for the left and rights cases, as well as a pattern matching syntax alla Haskell, mapper methods for each sides, and more.
There is a stand-alone implementation of Either for Java 8 in a small library, "ambivalence": http://github.com/poetix/ambivalence
It is closest to the Scala standard implementation - for example, it provides left and right projections for map and hashMap operations.
There is no direct access to the left or right values; rather, you join the two types by providing lambdas to map them into a single result type:
Either<String, Integer> either1 = Either.ofLeft("foo");
Either<String, Integer> either2 = Either.ofRight(23);
String result1 = either1.join(String::toUpperCase, Object::toString);
String result2 = either2.join(String::toUpperCase, Object::toString);
You can get it from Maven central:
<dependency>
<groupId>com.codepoetics</groupId>
<artifactId>ambivalence</artifactId>
<version>0.2</version>
</dependency>
You don't need to settle with the instanceof checks or redundant fields. Surprisingly enough, Java's type system provides enough features to simulate the sum types cleanly.
Background
First of all, do you know that any data type can be encoded with just functions? It's called Church encoding. E.g., using the Haskell signature, the Either type could be defined as follows:
type Either left right =
forall output. (left -> output) -> (right -> output) -> output
You can interpret it as "given a function on the left value and a function on the right value, produce the result of either of them".
Definition
Expanding on this idea, in Java we can define an interface called Matcher, which includes both functions and then define the Sum type in terms of how to pattern-match on it. Here's the complete code:
/**
* A sum class which is defined by how to pattern-match on it.
*/
public interface Sum2<case1, case2> {
<output> output match(Matcher<case1, case2, output> matcher);
/**
* A pattern-matcher for 2 cases.
*/
interface Matcher<case1, case2, output> {
output match1(case1 value);
output match2(case2 value);
}
final class Case1<case1, case2> implements Sum2<case1, case2> {
public final case1 value;
public Case1(case1 value) {
this.value = value;
}
public <output> output match(Matcher<case1, case2, output> matcher) {
return matcher.match1(value);
}
}
final class Case2<case1, case2> implements Sum2<case1, case2> {
public final case2 value;
public Case2(case2 value) {
this.value = value;
}
public <output> output match(Matcher<case1, case2, output> matcher) {
return matcher.match2(value);
}
}
}
Usage
And then you can use it like this:
import junit.framework.TestCase;
public class Test extends TestCase {
public void testSum2() {
assertEquals("Case1(3)", longOrDoubleToString(new Sum2.Case1<>(3L)));
assertEquals("Case2(7.1)", longOrDoubleToString(new Sum2.Case2<>(7.1D)));
}
private String longOrDoubleToString(Sum2<Long, Double> longOrDouble) {
return longOrDouble.match(new Sum2.Matcher<Long, Double, String>() {
public String match1(Long value) {
return "Case1(" + value.toString() + ")";
}
public String match2(Double value) {
return "Case2(" + value.toString() + ")";
}
});
}
}
With this approach you can even find a direct resemblance of pattern-matching in such languages as Haskell and Scala.
Library
This code is distributed as part of my library of composite types (Sums and Products, aka Unions and Tuples) of multiple arities. It's on GitHub:
https://github.com/nikita-volkov/composites.java
Since you've tagged Scala, I'll give a Scala answer. Just use the existing Either class. Here's an example usage:
def whatIsIt(flag: Boolean): Either[Int,String] =
if(flag) Left(123) else Right("hello")
//and then later on...
val x = whatIsIt(true)
x match {
case Left(i) => println("It was an int: " + i)
case Right(s) => println("It was a string: " + s)
}
This is completely type-safe; you won't have problems with erasure or anything like that...
And if you simply can't use Scala, at least use this as an example of how you can implement your own Either class.
The closest I can think of is a wrapper around both values that lets you check which value is set and retrieve it:
class Either<TLeft, TRight> {
boolean isLeft;
TLeft left;
TRight right;
Either(boolean isLeft, TLeft left1, TRight right) {
isLeft = isLeft;
left = left;
this.right = right;
}
public boolean isLeft() {
return isLeft;
}
public TLeft getLeft() {
if (isLeft()) {
return left;
} else {
throw new RuntimeException();
}
}
public TRight getRight() {
if (!isLeft()) {
return right;
} else {
throw new RuntimeException();
}
}
public static <L, R> Either<L, R> newLeft(L left, Class<R> rightType) {
return new Either<L, R>(true, left, null);
}
public static <L, R> Either<L, R> newRight(Class<L> leftType, R right) {
return new Either<L, R>(false, null, right);
}
}
class Main {
public static void main(String[] args) {
Either<String,Integer> foo;
foo = getString();
foo = getInteger();
}
private static Either<String, Integer> getInteger() {
return Either.newRight(String.class, 123);
}
private static Either<String, Integer> getString() {
return Either.newLeft("abc", Integer.class);
}
}
Based on the answer by Riccardo, following code snippet worked for me:
public class Either<L, R> {
private L left_value;
private R right_value;
private boolean right;
public L getLeft() {
if(!right) {
return left_value;
} else {
throw new IllegalArgumentException("Left is not initialized");
}
}
public R getRight() {
if(right) {
return right_value;
} else {
throw new IllegalArgumentException("Right is not initialized");
}
}
public boolean isRight() {
return right;
}
public Either(L left_v, Void right_v) {
this.left_value = left_v;
this.right = false;
}
public Either(Void left_v, R right_v) {
this.right_value = right_v;
right = true;
}
}
Usage:
Either<String, Integer> onlyString = new Either<String, Integer>("string", null);
Either<String, Integer> onlyInt = new Either<String, Integer>(null, new Integer(1));
if(!onlyString.isRight()) {
String s = onlyString.getLeft();
}
Change your design so that you don't need this rather absurd feature. Anything you'd do with the return value would require some sort of if/else construct. It would just be very, very ugly.
From a quick Googling, it seems to me that the only thing Haskell's Either is commonly used for is error reporting anyway, so it looks like exceptions are actually to correct replacement.