Java继承,如何重写子类中的方法

Java继承,如何重写子类中的方法,java,inheritance,Java,Inheritance,我正在练习一个面试问题。问题是实现一个排序的堆栈,只使用一个以上的堆栈进行临时存储 实现描述:我正在扩展Stack类以实现SortedStack类。SortedStack类的大多数方法与Stack类相同,所以我不需要实现它们。只有push方法被重写 在我的实现中,我将当前堆栈传递给push方法。我的问题是:这是访问现有堆栈的最佳方式吗。我可以访问堆栈的内容而不将其传递给push()方法吗 Node.java public class Node { private int key;

我正在练习一个面试问题。问题是实现一个排序的堆栈,只使用一个以上的堆栈进行临时存储

实现描述:我正在扩展Stack类以实现SortedStack类。SortedStack类的大多数方法与Stack类相同,所以我不需要实现它们。只有push方法被重写

在我的实现中,我将当前堆栈传递给push方法。我的问题是:这是访问现有堆栈的最佳方式吗。我可以访问堆栈的内容而不将其传递给push()方法吗

Node.java

public class Node {
    private int key;
    private float value;

    public Node(int key, float value) {
        this.key = key;
        this.value = value;
    }

    public int getKey() { return key; }
    public void setKey(int key) { this.key = key; }

    public float getValue() { return value; }
    public void setValue(float value) { this.value = value; }
}
import java.util.Stack;

public class SortedStack extends Stack {

    public SortedStack() {
        super();
    }

    public void push(Stack<Node> mainStack, Node newNode) {
        Stack<Node> tempStack = new Stack<Node>();

        while (!mainStack.isEmpty()) {
            if (mainStack.peek().getKey() > newNode.getKey()) {
                tempStack.push(mainStack.pop());
            }
            else {
                break;
            }
        }

        mainStack.push(newNode);

        while (!tempStack.isEmpty()) {
            mainStack.push(tempStack.pop());
        }
    }

}
public class SortedStackApp {

    public static void main(String[] args) {

        SortedStack stack = new SortedStack();

        stack.push(stack, new Node(10, 1.1f));
        stack.push(stack, new Node(80, 1.8f));
        stack.push(stack, new Node(50, 1.5f));
        stack.push(stack, new Node(90, 1.9f));
        stack.push(stack, new Node(20, 1.2f));
        stack.push(stack, new Node(30, 1.3f));

        Node node = null;

        while (!stack.isEmpty()) {
            node = (Node) stack.pop();
            System.out.printf("(%d, %3.1f) ", node.getKey(), node.getValue());
        }
        System.out.println();
    }
}
SortedStack.java

public class Node {
    private int key;
    private float value;

    public Node(int key, float value) {
        this.key = key;
        this.value = value;
    }

    public int getKey() { return key; }
    public void setKey(int key) { this.key = key; }

    public float getValue() { return value; }
    public void setValue(float value) { this.value = value; }
}
import java.util.Stack;

public class SortedStack extends Stack {

    public SortedStack() {
        super();
    }

    public void push(Stack<Node> mainStack, Node newNode) {
        Stack<Node> tempStack = new Stack<Node>();

        while (!mainStack.isEmpty()) {
            if (mainStack.peek().getKey() > newNode.getKey()) {
                tempStack.push(mainStack.pop());
            }
            else {
                break;
            }
        }

        mainStack.push(newNode);

        while (!tempStack.isEmpty()) {
            mainStack.push(tempStack.pop());
        }
    }

}
public class SortedStackApp {

    public static void main(String[] args) {

        SortedStack stack = new SortedStack();

        stack.push(stack, new Node(10, 1.1f));
        stack.push(stack, new Node(80, 1.8f));
        stack.push(stack, new Node(50, 1.5f));
        stack.push(stack, new Node(90, 1.9f));
        stack.push(stack, new Node(20, 1.2f));
        stack.push(stack, new Node(30, 1.3f));

        Node node = null;

        while (!stack.isEmpty()) {
            node = (Node) stack.pop();
            System.out.printf("(%d, %3.1f) ", node.getKey(), node.getValue());
        }
        System.out.println();
    }
}

堆栈是java.util.Stack,如所述:

这是唯一的方法。您无法访问直接数据,因为它作为私有数据存储在节点中,然后发送到堆栈

首先,如果要扩展
java.util.Stack
,则应为其提供基本类型。这是错误的:

public class SortedStack extends Stack {...}
在这种情况下,
堆栈
是一种原始类型。原始类型只应与旧代码一起使用,因为您将失去类型安全性。相反,您应该使用:

public class SortedStack extends Stack<Node> {...}
您应该使用以下命令从
main
调用它:

stack.push( new Node( 10, 1.1f ) );
由于已使用类型正确声明了它,因此不需要将
pop
的结果强制转换为
节点

node = stack.pop(); // No need for (Node)

现在我们有了一个正确类型的类,那么,您的项就是堆栈。这就是继承的实际含义:“我现在编写的这个类是一个
堆栈
,它拥有所有
堆栈
方法,并存储所有
堆栈
数据,我只是在改变它的一些行为。”

因此,要访问“主”堆栈,它只需访问本身。例如,while循环应该是:

@Override
public Node push(Node n) {
   ...
}
    while (!this.empty()) {
        if (this.peek().getKey() > n.getKey()) {
            tempStack.push(this.pop());
        }
        else {
            break;
        }
    }
    while (!empty() && peek().getKey() > n.getKey() ) {
        tempStack.push(pop());
    }
实际上,您也可以去掉
这个
,因为这里没有歧义。调用
empty()
与调用
this.empty()
相同(您在代码中使用了
isEmpty()
,但
java.util.Stack
只有
empty()

所以它真的应该是:

@Override
public Node push(Node n) {
   ...
}
    while (!this.empty()) {
        if (this.peek().getKey() > n.getKey()) {
            tempStack.push(this.pop());
        }
        else {
            break;
        }
    }
    while (!empty() && peek().getKey() > n.getKey() ) {
        tempStack.push(pop());
    }
(我稍微改进了你的循环,如果,就不需要额外的

但是,要小心使用
this.push()
或仅使用
push()
来获取主堆栈。您可以改用
super.push()
。这样,它将使用原始行为
项推送到实际堆栈中:

    super.push(n); // Don't use new Node() here. Push the node you were given.

    while (!tempStack.empty()) {
        super.push(tempStack.pop());
    }
如果不这样做,您将以递归方式调用您正在编写的
push
。这将不是您想要的-您希望在内部使用“普通”推送

完成后,请记住返回插入的
节点


另一种选择是不扩展
堆栈
,而是重新实现所有方法并拥有一个内部堆栈。查看“组合与继承”以确定哪一个更好。

这不是一个好的实现,因为您正在重载
push()
而不是重写它。使用堆栈的用户仍将使用带有一个参数的
push
。请检查重载和重写。我会使用一个堆栈。是的,您必须从堆栈中创建所有方法,但您可以访问整个堆栈,并可以根据需要修改推送方法。@Real怀疑论者,同意重写优于重载。特别是因为我使用了堆栈中的所有其他方法。你的评论有助于更好地重新表述我的问题。我最初的问题是:我可以访问堆栈的内容而不将其传递给push()方法吗?所以我建议您编辑您的问题并相应地更改它。我还建议添加
堆栈
类本身,因为很难猜到您继承了什么方法等等。我已经更新了问题,以反映您建议的更改。我还将更新SortedStack和SortedStackApp,以便将节点传递给push()方法,而不是键和值。谢谢您的回答。在我看来,我认为在SortedStack中的任何地方使用“this”都是指Node类型的对象,而不是堆栈本身。你的详细解释涵盖了我遇到的每一个问题,事实上,你也预料到了我会遇到的任何其他问题。你提到了组合与继承。我一定会查一查,了解相关的利弊。在我最初的实现中,我的SortedSort并没有扩展堆栈,而是使用了一个内部堆栈。我觉得使用继承对我来说是一种学习经历,当然是!