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