In this code:
public interface LinkedList<T> {
<N extends Node<T>> Optional<N> findNodeByData(T data);
// ...
}
public class SinglyLinkedListNode<T> extends Node<T> {
// ...
}
public class Node<T> {
// ...
}
public class SinglyLinkedList<T> implements LinkedList<T> {
public Optional<SinglyLinkedListNode<T>> findNodeByData(T data){
// ...
}
}
My goal is to have the method in interface accept any class that extends Node<T>
, as N
.
I get the error 'findNodeByData(T)' in 'com.starosti.datastructures.linkedlist.singly.SinglyLinkedList' clashes with 'findNodeByData(T)' in 'com.starosti.datastructures.linkedlist.LinkedList'; both methods have same erasure, yet neither overrides the other
in the line that findNodeByData
is defined in SinglyLinkedList<T>
.
How do I fix this issue? Is there a better way to do this?
CodePudding user response:
The erasure of the return types is Optional
, yet Optional<SinglyLinkedListNode<T>>
is not a subtype of Optional<Node<T>>
, explaining your compiler error.
By PECS (Producer: Extends, Consumer: Super), your Node
produces the value, so it's safe to use a wildcard upper bound ("extends") on the return type of the method findNodeByData
.
interface LinkedList<T> {
Optional<? extends Node<T>> findNodeByData(T data);
}
This allows you to override the method in the concrete subclass with a subtype, according to covariant return types. Also, when overriding, always include the @Override
annotation, so the compiler can check for you if you're truly overriding the method or merely overloading it accidentally.
class SinglyLinkedList<T> implements LinkedList<T> {
@Override
public Optional<SinglyLinkedListNode<T>> findNodeByData(T data){
// ...
}
}