Reputation: 989
I have a class with a constructor signature as follows:
public class MyClass <U>{
public <T> MyClass(Set<T> data, Function<T,U> func)...
}
That's fine. But I want to overload the constructor, for the case that if you don't provide Function func
, it will just use (item)->{return item;}
. I've written another constructor that looks like this:
public <T> MyClass(Set<T> data){
this(
data,
(item)->{return item;}
);
}
This is causing a type mismatch error, because the function I'm providing as an argument to my constructor takes a value of type T
, and returns that same value, which should be a U
. I don't understand why the algebraic type system doesn't see that in this case U and T are the same and that's ok?
Upvotes: 5
Views: 353
Reputation: 13535
Since you declared two distinct types T and U, compiler reasonably thinks they are different. If they are the same, do not declare T and use only U:
public MyClass(Set<U> data){
this(
data,
(item)->{return item;}
);
}
Upvotes: 0
Reputation: 394026
Let's try to create an instance of your class using the second constructor :
Set<Integer> ints = new HashSet<>();
MyClass<String> myobj = new <Integer> MyClass (ints);
your first constructor would expect a Set<Integer>
and a Function<Integer,String>
parameters, but your second constructor would try to pass to it a Function<Integer,Integer>
. That's the reason your code doesn't pass compilation.
When you define generic classes and methods, they must be valid for any combination of types that can substitute their type parameters.
Upvotes: 3
Reputation: 1676
The system has to assume that T and U are two different types, since you gave them two different names. But you can just remove the additional generic type from your second ctor like that:
public class MyClass <U>{
public <T> MyClass(Set<T> data, Function<T,U> func) {...}
public MyClass(Set<U> data){
this(
data,
(item)->{return item;}
);
}
}
Upvotes: 7