Himanshu Bisht
Himanshu Bisht

Reputation: 11

How interface works with generics subtyping in java?

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

Answers (2)

ernest_k
ernest_k

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

Ga&#235;l J
Ga&#235;l J

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

Related Questions