Reputation: 11
Consider the following classes.
class Shape {}
class Circle extends Shape {}
class Rectangle extends Shape {}
class Node <T> {}
// In main method
Node<Circle> circleNode = new Node<>();
Node<Shape> shapeNode = circleNode; // ERROR
Following code will not compile because even though Circle is a subtype of Shape. Because of generics subtyping.
But now consider the new Node class.
class Node<T> implements Comparable<T> {
public int compareTo(T obj) { /* ... */ }
// ...
}
// In main method
Node<String> stringNode = new Node<>();
Comparable<String> comparable = stringNode;
Following code successfully compile. But there is no explanation on Java Docs. How implementing an interface make it compile successfully. And I didn't understand what happened exactly.
Upvotes: 0
Views: 68
Reputation: 45329
You're comparing apples and oranges.
In your example, Node<Shape>
is to Node<Circle>
as List<Animal>
is to List<Dog>
.
However, Comparable<String>
is to Node<String>
as List<Animal>
is to ArrayList<Animal>
.
If you can have this parallelism clear in mind, all you need to remember is that a List<Dog>
is not a List<Animal>
and you have your answer.
stringNode
is a Node<String>
, and that means assigning that variable to a Comparable<String>
-typed variable only requires the base type's relationship. That's because the declaration Node<T> implements Comparable<T>
makes Node
a Comparable
subtype. With the type parameter being exactly the same, that makes Comparable<String>
assignable from Node<String>
(just as List<String>
is assignable from ArrayList<String>
)
In other words, the difference is not due to "implementing an interface make it compile successfully"... it's due to the fact that Node<Shape>
is not assignable from Node<Circle>
(which you seem to understand), whether node is an interface or not.
Upvotes: 1
Reputation: 15250
In 2nd example you're saying that for a given T
a Node<T>
is a Comparable<T>
. Thus, for T = String
you have Node<String>
is a Comparable<String>
.
However in 1st example you have 2 different types T
and U
where T
is a U
but there is nothing that says that Node<T>
is a Node<U>
.
You might want to look for covariance and contravariance to learn more on this topic.
Upvotes: 0