如何使子类接受超类作为值?

时间:2016-04-10 02:54:11

标签: java tree subclass

我有一个名为Tree的超类和一个名为AVLTree的子类,它扩展了类Tree。

树的子项也是Tree类型。 AVLTree有AVLTree的孩子。我想使用我在Tree类上编写的方法,在这种情况下getLeft(返回左子)和setLeft(设置左子)。

问题是编译器无法将树转换为AVLTree,即使它们具有相同的变量,结构和构造函数。

关于如何解决这个问题的任何想法?或者我应该只写一个AVLTree在Tree类上的所有方法吗?

代码:

Tree.java:

public class Tree<T extends Tree<T>> {
  private T left = null;
  private T right = null;
  private Object data = null;

  public Tree () {
    //nothing
  }
  public Tree (Object data, T left, T right) {
    this.data = data;
    this.left = left;
    this.right = right;
  }
  public Tree (Object data) {
    this.data = data;
  }


  //Get Values
  public T getLeft() {
    return this.left;
  }
  public T getRight() {
    return this.right;
  }
  public Object getData() {
    return this.data;
  }
  //Set Values
  public void setLeft(T left) {
    this.left = left;
  }
  public void setRight(T right) {
    this.right = right;
  }
  public void setData(Object data) {
    this.data = data;
  }

  public T treeFromText(String in) {
    if (in=="()") return null;
    int i=0;
    T result = null;
    //Find expression
    int d = in.indexOf('c')+1;
    if (d==0) return null;


    int begl, endl, begr, endr;

    begl = d+1;
    endl = ClosingParentesis(in,begl);
    endr = in.length()-2;
    begr = OpeningParentesis(in,endr);

    T left = null, right = null;

    if (begl-endl==0) {
      left = null;
    } else left = treeFromText(in.substring(begl,endl+1));
    if (begr-endr==0) {
      right = null;
    } else right = treeFromText(in.substring(begr,endr+1));

    result.setData(in.charAt(d));
    result.setLeft(left);
    result.setRight(right);
    return result;
  }


  public static int ClosingParentesis(String in, int openPos) {
    int closePos = openPos;
    int counter = 1;
    while (counter > 0 && closePos < in.length()-1) {
      closePos++;
      if (in.charAt(closePos)=='(') counter++;
      if (in.charAt(closePos)==')') counter--;
    }
    return closePos;
  }

  public static int OpeningParentesis(String in, int closePos) {
    int openPos = closePos;
    int counter = 1;
    while (counter > 0 && openPos > 0) {
      openPos--;
      if (in.charAt(openPos)=='(') counter--;
      if (in.charAt(openPos)==')') counter++;
    }
    return openPos;
  }

AVLTree.java:

public class AVLTree extends Tree<AVLTree> {
  /*
  //Values and Variables
  private AVLTree left = null;
  private AVLTree right = null;
  private Object data;


  //Inicialization
  public AVLTree (Object data, AVLTree left, AVLTree right) {
    super(data,left,right);
  }
  public AVLTree (Object data) {
    super(data);
  }


  */
  public int getfactor() {
    return getHeight(this.getLeft())-getHeight(this.getRight());
  }
}

Test.java:

public static void main(String[] args) {
  AVLTree tree = new AVLTree();

  Scanner console = new Scanner(System.in);
  String in = console.nextLine().toLowerCase();

  tree = (AVLTree) tree.treeFromText(in); //The error is here.
  System.out.println(tree.getHeight());
  System.out.println(tree.TreePreOrder());


}

我期望它的工作方式是,如果字符串&#39;在&#39;在Test.java中是&#34;(c3()(c2()()))&#34;返回值必须是值为3的Tree和值为2的右子。此返回值必须是Tree类型或任何扩展Tree的值。

2 个答案:

答案 0 :(得分:0)

你可以通过泛型的力量来实现这一点:定义一个新的循环泛型T:

public class Tree<T extends Tree<T>>
{
    T left;
    T right;

    public T doSomething()
    {
        return left;
    }

    public static class AVLTree extends Tree<AVLTree>
    {
        public AVLTree foo()
        {
            return doSomething();
        }
    }
} 

更新:以下是创建不同树实例的方法:

import java.util.Objects;

public class TreesFactory
{
    public static AVLTree createAVLTreeFrom(String in)
    {
        return treeFromText(in, AVLTree::new);
    }

    @FunctionalInterface
    interface SimpleFactory<T extends Tree<T>>
    {
        T createNew();
    }

    public static <T extends Tree<T>> T treeFromText(String in, SimpleFactory<T> treeFactory)
    {
        if (Objects.equals(in, "()"))
            return null;

        T result = treeFactory.createNew();
        //Find expression
        int d = in.indexOf('c') + 1;
        if (d == 0)
            return null;

        int begl, endl, begr, endr;

        begl = d + 1;
        endl = ClosingParentesis(in, begl);
        endr = in.length() - 2;
        begr = OpeningParentesis(in, endr);

        T left, right;

        if (begl - endl == 0)
        {
            left = null;
        }
        else
            left = treeFromText(in.substring(begl, endl + 1), treeFactory);
        if (begr - endr == 0)
        {
            right = null;
        }
        else
            right = treeFromText(in.substring(begr, endr + 1), treeFactory);

        result.setData(in.charAt(d));
        result.setLeft(left);
        result.setRight(right);
        return result;
    }


    public static int ClosingParentesis(String in, int openPos)
    {
        int closePos = openPos;
        int counter = 1;
        while (counter > 0 && closePos < in.length() - 1)
        {
            closePos++;
            if (in.charAt(closePos) == '(')
                counter++;
            if (in.charAt(closePos) == ')')
                counter--;
        }
        return closePos;
    }

    public static int OpeningParentesis(String in, int closePos)
    {
        int openPos = closePos;
        int counter = 1;
        while (counter > 0 && openPos > 0)
        {
            openPos--;
            if (in.charAt(openPos) == '(')
                counter--;
            if (in.charAt(openPos) == ')')
                counter++;
        }
        return openPos;
    }
}

主要:

public static void main(String[] args)
{
    Scanner console = new Scanner(System.in);
    String in = console.nextLine().toLowerCase();

    AVLTree tree = TreesFactory.createAVLTreeFrom(in);
    //...
}

答案 1 :(得分:0)

您需要一种方法,使用AVLTree中的逻辑从String实例化Tree.treeFromText

  1. Tree声明为abstract

  2. Tree中创建一个新方法:

    abstract protected T createEmptyTree();

  3. AVLTree中覆盖该方法,以返回AVLTree的空实例。

    @Override protected AVLTree createEmptyTree() { return new AVLTree(); }

  4. treeFromText()中,只要您需要创建T的空实例,请调用createEmptyTree()

  5. 你已经拥有了其余的逻辑。

    尽量避免在任何地方返回null。最好返回空AVLTree而不是null