Java继承,如何覆盖子类

时间:2015-12-08 18:10:38

标签: java inheritance

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

实现描述:我正在扩展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; }
}

SortedStack.java

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

}

SortedStackApp.java

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

Stack是java.util.Stack,如:http://docs.oracle.com/javase/7/docs/api/java/util/Stack.html

所述

2 个答案:

答案 0 :(得分:1)

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

public class SortedStack extends Stack {...}

在这种情况下,Stack原始类型。原始类型应仅与遗留代码一起使用,因为您失去了类型安全性。相反,你应该使用:

public class SortedStack extends Stack<Node> {...}

这样做会自动使您的堆栈仅接受Node元素。

正如我在评论中所说,你应该覆盖 push方法,而不是重载它。这意味着它必须具有与父类的push方法完全相同的参数。因此,它应该只采用Node参数,就是这样。使用@Override注释标记方法,以确保您真正覆盖它而不是重载。如果您有额外的参数或不兼容的参数类型,编译器将发出错误。

您将注意到,一旦您这样做,您必须更改方法的声明以返回Node,因为这是在push中声明java.util.Stack的方式。

所以你的方法应该是:

@Override
public Node push(Node n) {
   ...
}

您应该使用以下代码从main拨打电话:

stack.push( new Node( 10, 1.1f ) );

由于您已使用该类型正确声明,因此您无需将pop的结果转换为Node

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

既然我们有一个正确输入的类,那么你的项堆栈。这就是继承实际上意味着什么:“我现在写的这个类是Stack并且拥有所有Stack方法,并且存储了所有Stack数据,我只是在改变一些它的行为。“

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

    while (!this.empty()) {
        if (this.peek().getKey() > n.getKey()) {
            tempStack.push(this.pop());
        }
        else {
            break;
        }
    }

实际上,你也可以摆脱this,因为没有歧义。致电empty()与调用this.empty()相同(您在代码中使用了isEmpty(),但java.util.Stack只有empty())。

所以它应该是:

    while (!empty() && peek().getKey() > n.getKey() ) {
        tempStack.push(pop());
    }

(我改进了你的循环,不需要额外的if)。

但是,请注意使用this.push()push()来获取主堆栈。您可以改用super.push()。这样它将使用原始行为push项目进入实际堆栈:

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

    while (!tempStack.empty()) {
        super.push(tempStack.pop());
    }

如果你不这样做,你将以递归方式调用你正在写的push。这不是你想要的 - 你想要在内部使用“普通”推动。

请务必在完成后返回您插入的Node

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

答案 1 :(得分:-1)

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