I have a rather weird question. Consider the following two classes:
public class Node<T> {
private Node<T> parent;
private Node<T> left;
private Node<T> right;
private T data;
public Node(Node<T> parent, T data) {
this.parent = parent;
this.data = data;
}
public Node<T> getParent() {
return parent;
}
public void setParent(Node<T> parent) {
this.parent = parent;
}
public Node<T> getLeft() {
return left;
}
public void setLeft(Node<T> left) {
this.left = left;
}
public Node<T> getRight() {
return right;
}
public void setRight(Node<T> right) {
this.right = right;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
and
public class RedBlackNode<T> extends Node<T> {
private Color color;
public RedBlackNode(Node<T> parent, T data) {
super(parent, data);
this.color = Color.Black;
}
public RedBlackNode(Node<T> parent, T data, Color color) {
super(parent, data);
this.color = color;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}
My question is .. is there any way in which I could write:
RedBlackNode<Whatever> x = y.getLeft();
where y is a RedBlackNode
without having to specifically cast using:
RedBlackNode<Whatever> x = (RedBlackNode<Whatever>) y.getLeft();
and also, without having to override the getters/setters in the RedBlackNode class?
I mean, I just want to somehow make the RedBlackNode be "aware" that it's a RedBlackNode and know that all its children/parent are actually RedBlackNodes as well. I am not sure but maybe somehow add a new abstraction layer on top of the Node class somehow maybe?
Ty!
Later edit:
Thank you for all your prompt answers, this is what I have so far:
public abstract class AbstractNode<T, U extends AbstractNode<T, U>> {
private AbstractNode<T, U> parent;
private AbstractNode<T, U> left;
private AbstractNode<T, U> right;
private T data;
public AbstractNode(AbstractNode<T, U> parent, T data) {
this.parent = parent;
this.data = data;
}
public AbstractNode<T, U> getParent() {
return parent;
}
public void setParent(AbstractNode<T, U> parent) {
this.parent = parent;
}
public AbstractNode<T, U> getLeft() {
return left;
}
public void setLeft(AbstractNode<T, U> left) {
this.left = left;
}
public AbstractNode<T, U> getRight() {
return right;
}
public void setRight(AbstractNode<T, U> right) {
this.right = right;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
public class RedBlackNode<T extends Element> extends AbstractNode<Element, RedBlackNode<Element>> {
private Color color;
public RedBlackNode(RedBlackNode<Element> parent, T data) {
super(parent, data);
this.color = Color.Black;
}
public RedBlackNode(RedBlackNode<Element> parent, T data, Color color) {
super(parent, data);
this.color = color;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}
public class Node<T> extends AbstractNode<T, Node<T>> {
public Node(AbstractNode<T, Node<T>> parent, T data) {
super(parent, data);
}
}
However, I need to create 2 types of trees. A simple Binary Search Tree which has as nodes only instances of class Node and, as expected, a Red Black Tree which has only instances of RedBlackNode as nodes.
I made an abstract class for these trees (with many more methods, this is the trimmed version) but I fear that I am missing something as I seem to have this Node<Element>
as the generic type in the class definition.
public abstract class Tree<T extends AbstractNode<Element, Node<Element>>> {
protected T root;
public T getRoot() {
return this.root;
}
public abstract T search(T n, int key);
public abstract T insert(Element e, T cRoot);
}
What am I missing here? How to best model this?
Later edit 2:
I currently have:
public abstract class AbstractNode<E extends Element, U extends AbstractNode<E, U>> {
private U parent;
private U left;
private U right;
private E data;
public AbstractNode(U parent, E data) {
this.parent = parent;
this.data = data;
}
public U getParent() {
return parent;
}
public void setParent(U parent) {
this.parent = parent;
}
public U getLeft() {
return left;
}
public void setLeft(U left) {
this.left = left;
}
public U getRight() {
return right;
}
public void setRight(U right) {
this.right = right;
}
public E getData() {
return data;
}
public void setData(E data) {
this.data = data;
}
}
public class Node<E extends Element> extends AbstractNode<E, Node<E>> {
public Node(Node<E> parent, E data) {
super(parent, data);
}
}
public class RedBlackNode<E extends Element> extends AbstractNode<E, RedBlackNode<E>> {
private Color color;
public RedBlackNode(RedBlackNode<E> parent, E data) {
super(parent, data);
this.color = Color.Black;
}
public RedBlackNode(RedBlackNode<E> parent, E data, Color color) {
super(parent, data);
this.color = color;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}
The Tree class:
public abstract class Tree<E extends Element, T extends AbstractNode<E, T>> {
protected T root;
public T getRoot() {
return this.root;
}
public abstract T search(T n, int key);
}
AND The BinarySearchTreeClass
public class BinarySearchTree<Element> extends Tree<Element, Node<Element>> {
@Override
public Node<Element> search(Node<Element> n, int key) {
if (n == null || n.getData().getIntegerData() == key) {
return n;
}
return key < n.getData().getIntegerData() ? search( n.getLeft(), key) : search( n.getRight(), key);
}
}
Why in the world am I getting Bound mismatch: The type Element is not a valid substitute for the bounded parameter <E extends Element> of the type Node<E>
. It's E extends Element
. Doesn't that mean it can be of type Element
as well?
Nevertheless, I tried using something like a separate class which extended Element
but to no avail..
Also, I am getting a The type parameter Element is hiding the type Element
and I have no idea why..
I created a GIST for this.