在getter / setter中自动转换为子类

时间:2015-06-09 17:16:32

标签: java oop

我有一个相当奇怪的问题。考虑以下两个类:

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;
    }

}

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;
    }

}

我的问题是......我有什么方法可以写:

RedBlackNode<Whatever> x = y.getLeft();

其中y是RedBlackNode,无需使用:

进行特定投射
RedBlackNode<Whatever> x = (RedBlackNode<Whatever>) y.getLeft();

并且,无需覆盖RedBlackNode类中的getter / setter?

我的意思是,我只想以某种方式让RedBlackNode“意识到”它是一个RedBlackNode,并且知道它的所有子/父实际上也是RedBlackNodes。我不确定但也许某种程度上可能以某种方式在Node类之上添加一个新的抽象层?

泰!

稍后编辑:

感谢您提供的所有快速答案,这是我目前所做的:

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);
    }

}

但是,我需要创建两种类型的树。一个简单的二进制搜索树,它只有Node节点的实例,并且如预期的那样,只有RedBlackNode实例作为节点的Red Black Tree。

我为这些树做了一个抽象类(有更多的方法,这是修剪后的版本)但是我担心我错过了一些东西,因为我似乎将这个Node<Element>作为类定义中的泛型类型

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);
}

我在这里缺少什么?如何最好地模拟这个?

稍后编辑2:

我目前有:

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;
    }

}

树类:

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);
}

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);
    }

}

为什么我在世界上Bound mismatch: The type Element is not a valid substitute for the bounded parameter <E extends Element> of the type Node<E>。它是E extends Element。这是不是意味着它也可以是Element类型? 尽管如此,我尝试使用类似于扩展Element但没有用的单独类的东西。

另外,我收到了The type parameter Element is hiding the type Element,我不知道为什么......

我为此创建了GIST

1 个答案:

答案 0 :(得分:4)

如果您不介意将Node拉出到抽象类中,您可以将类型指定为通用签名的一部分,如下所示:

public abstract class AbstractNode<T, U extends AbstractNode<T, U>> {
    ...
    public U getLeft() {
        ...
    }
    ...
}

// inherited getLeft() will return Node<T>
public class Node<T> extends AbstractNode<T, Node<T>> { ... }

// inherited getLeft() will return RedBlackNode<T>
public class RedBlackNode<T> extends AbstractNode<T, RedBlackNode<T>> { ... }

编辑:对于您的树,您可以为每个节点类型创建一个单独的树,或者如果您想重用基本功能,您可以执行以下操作:

// base functionality goes here, T is the element type, U is the node type
public abstract class Tree<T, U extends AbstractNode<T, U>> { ... }

public class BinarySearchTree<T> extends Tree<T, Node<T>> { ... }

public class RedBlackTree<T> extends Tree<T, RedBlackNode<T>> { ... }

或者如果您只想共享方法签名,则将Tree设为接口而不是抽象类。或者更好的是,有一个Tree接口和一个实现共享功能的AbstractTree抽象类。

相关问题