如何使用继承从同一函数 return 不同类型?

how to return different type from same function using inhertinace?

比如我想创建父class节点,子class是IntegerNode和CharacterNode。 并尝试在不知道值类型的情况下查找列表中是否已存在值。 为此,我将发送我的 Node 对象,并在运行时期间获得适当的值。

有一种方法可以不使用实例吗?

public class CharNode extends Node {

    private Character charNode;

    CharNode(char digit){
        this.charNode = digit;
    }
    
    Character getValue(){
        return charNode;
    }
}


public class IntegerNode extends Node {
    private Integer integerNode;

    IntegerNode(int number){
        this.integerNode = number;
    }

    Integer getValue(){
        return integerNode;
    }
}



public class Node {

    Node getNode();
}




  boolean isExists(List<Node> list, Node value){
   ///// Here I want to check if the value inside the node already exists in that list without checking the type. It can be Lists of characters or a list of integers.

}

最简单的方法是为 类:

实现 equals 方法
// equals for the CharNode class
public boolean equals(final Object o) {
  if (this == o) return true;
  if (o == null || getClass() != o.getClass()) return false;
  // add here the logic specific to each class
  return this.charNode.equals(((CharNode)o).charNode);
}
// equals for the IntegerNode class
public boolean equals(final Object o) {
  if (this == o) return true;
  if (o == null || getClass() != o.getClass()) return false;
  // add here the logic specific to each class
  return this.integerNode.equals(((IntegerNode)o).integerNode);
}

之后你就可以使用list.contains(node)方法

试试这个。

static abstract class Node {
    protected Object value;

    public Node(Object value) {
        this.value = value;
    }

    public Object getValue() {
        return value;
    }
}

static class CharacterNode extends Node {

    public CharacterNode(char value) {
        super(value);
    }
}

static class IntegerNode extends Node {

    public IntegerNode(int value) {
        super(value);
    }
}

public static void main(String[] args) {
    List<Node> nodes = List.of(new CharacterNode('a'), new IntegerNode(3));
    for (Node node : nodes)
        if (node.getValue().equals(3))
            System.out.println("found value 3");
}

输出:

found value 3

我对您的 class 做了一些改动,因此使用它们更容易。

public abstract class Node<T> {

    public abstract T getValue();

    // I guess you implemented this method, but didn't copy it in your example.
    //Node getNode();
    
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Node<?> otherNode = (Node<?>) o;
        T value = getValue();
        if (value == null) return otherNode.getValue() == null;
        return getValue().equals(otherNode.getValue());
    }
    
    // If you implement eqauls you should also always implement hashCode.
    public int hashCode() {
        T value = getValue();
        return value != null ? value.hashCode() : 0;
    }
}

public class CharNode extends Node<Character> {

    private Character value;

    public CharNode(char value){
        this.value = value;
    }
    
    @Override
    public Character getValue(){
        return value;
    }
}

public class IntegerNode extends Node<Integer> {
    
    private Integer value;

    public IntegerNode(int value){
        this.value = value;
    }

    @Override
    public Integer getValue(){
        return value;
    }
}

Node 现在是抽象的,并且添加了一个抽象方法 getValue。任何继承自 Node 的 class 现在都被迫实施 getValue。此外,我添加了 equalshashCode 的简单实现。在您的情况下,您可能只需要 equals,但在实施 equals 时不实施 hashCode 是非常糟糕的做法,并且可能会破坏依赖于有效实施的 classes。

现在只需遍历列表并每次检查 equals

public boolean isExists(List<? extends Node<?>> list, Node<?> value) {
    for (Node<?> node : list) {
        if (node.equals(value)) {
            return true;
        }
    }
    return false;
}

或者使用 List.contains 对我们也一样。

public boolean isExists(List<? extends Node<?>> list, Node<?> value) {
    return list.contains(value);
}

这里是一个使用 CharNodes 列表的例子。

CharNode sNode = new CharNode('s');
CharNode cNode = new CharNode('c');
IntegerNode oneNode = new IntegerNode(1);
IntegerNode twoNode = new IntegerNode(2);
List<CharNode> charNodes = Arrays.asList(sNode, cNode);
System.out.println(isExists(charNodes, new CharNode('s'))); // true
System.out.println(isExists(charNodes, new CharNode('x'))); // false

您还可以创建混合类型的节点列表。

List<Node<?>> allNodes = Arrays.asList(sNode, cNode, oneNode, twoNode);
System.out.println(isExists(allNodes, new CharNode('s'))); // true
System.out.println(isExists(allNodes, new IntegerNode(1)));  // true
System.out.println(isExists(allNodes, new CharNode('x'))); // false

您可以使用 Node.getValue() 来获取值,但是如果不知道 getValue() 的类型,您只能做这么多。

Object nodeValue = allNodes.get(3).getValue();
System.out.println(nodeValue); // 2

正如您提到的,您可以使用 instanceof 获取类型并为每个检查实例编写代码,但还有一个更好的解决方案:在 Node class 中添加另一个方法并在 children.

中为此方法实施适当的行为