简体   繁体   English

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

[英]Java inheritance, how to override a method in subclass

I am working on a practice interview question. 我正在研究实习面试问题。 The problem is to implement a sorted stack using only one more stack for temporary storage. 问题是仅使用一个以上的堆栈进行临时存储来实现排序的堆栈。

Description of implementation: I am extending Stack class to implement my SortedStack class. 实现的描述:我正在扩展Stack类以实现SortedStack类。 Most methods of SortedStack class are identical to Stack class, so I don't need to implement them. SortedStack类的大多数方法与Stack类相同,因此我不需要实现它们。 Only the push method is overridden. 仅推入方法被覆盖。

In my implementation, I am passing the current stack to push method. 在我的实现中,我将当前堆栈传递给push方法。 My question is: is this the best way to access the existing stack. 我的问题是:这是访问现有堆栈的最佳方法。 Can I access stack's contents without passing it to push() method? 我可以在不将其传递给push()方法的情况下访问其内容吗?

Node.java 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 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 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 is the java.util.Stack as described at: http://docs.oracle.com/javase/7/docs/api/java/util/Stack.html 堆栈是java.util.Stack,如以下网址所述: http : //docs.oracle.com/javase/7/docs/api/java/util/Stack.html

First thing, if you are extending java.util.Stack , you should provide a base type for it. 首先,如果要扩展java.util.Stack ,则应为其提供基本类型。 This is wrong: 这是错误的:

public class SortedStack extends Stack {...}

In this case, Stack is a raw type . 在这种情况下, Stack原始类型 Raw types should only be used with legacy code, as you lose the type safety. 原始类型只能与遗留代码一起使用,因为这样会失去类型安全性。 Instead, you should use: 相反,您应该使用:

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

Doing so will automatically make your stack accept only Node elements. 这样做将自动使您的堆栈仅接受Node元素。

As I said in the comments, you should be overriding the push method, not overloading it. 就像我在评论中说的那样,您应该重写 push方法,而不要重载它。 This means that it has to have exactly the same parameters as the parent class's push method. 这意味着它必须具有与父类的push方法完全相同的参数。 Thus, it should only take a Node parameter, and that's it. 因此,它仅应采用Node参数,仅此而已。 Mark the method with the @Override annotation to make sure that you are really overriding it and not overloading. 使用@Override批注标记该方法,以确保您确实覆盖了该方法,并且未超载。 The compiler will issue an error if you have extra parameters or incompatible parameter types. 如果您有其他参数或不兼容的参数类型,则编译器将发出错误。

You'll note, once you do that, that you have to change the declaration of the method to also return Node , as this is how push is declared in java.util.Stack . 您会注意到,一旦这样做,就必须更改方法的声明以也返回Node ,因为这是在java.util.Stack声明push方式。

So your method should be: 因此,您的方法应为:

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

And you should call it from your main using: 您应该使用以下命令从main调用它:

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

Since you have declared it properly with the type, you won't need to cast the result of pop to Node : 由于您已经使用类型正确声明了它,因此无需将pop的结果popNode

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

Now that we have a properly typed class, well, your item is the stack. 现在我们有了一个正确键入的类,那么,您的项目就是堆栈。 This is what inheritance actually means: "This class that I am writing now is a Stack and has all the Stack methods, and stores all the Stack data, I'm just changing some of its behavior." 这就是继承的真正含义:“我现在正在编写的这个类是一个Stack ,它具有所有Stack方法,并存储了所有Stack数据,我只是在更改其某些行为。”

So to access the "main" stack it simply needs to access itself . 因此,访问“主”堆栈只需要访问自身即可 For example, you while loop should be: 例如,您的while循环应为:

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

And really, you can also get rid of the this because there is no ambiguity. 实际上,您也可以摆脱this因为没有歧义。 Calling empty() is the same as calling this.empty() (you used isEmpty() in your code but java.util.Stack has only empty() ). 调用empty()与调用this.empty()相同(您在代码java.util.Stack使用了isEmpty() ,但java.util.Stack仅具有empty() )。

So it really should be: 所以实际上应该是:

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

(I improved your loop a bit, there was no need for the extra if ). (我对您的循环进行了一些改进,如果没有多余的if )。

However, beware of using this.push() or just push() to get your main stack. 但是,提防使用this.push()或只是push()来获取主堆栈。 You can use super.push() instead. 您可以改用super.push() That way it will use the original behavior to push the item into the actual stack: 这样,它将使用原始行为push项目push送到实际堆栈中:

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

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

If you don't do this, you will be calling the same push you are writing right now recursively. 如果您不这样做,您将递归调用与您现在正在编写的相同的push This will not be what you wanted - you wanted a "plain" push to be used internally. 这不是您想要的-您希望在内部使用“普通”按钮。

Remember to return the Node you inserted once you are done. 完成后,请记住返回您插入的Node

Another option would be to not extend Stack but re-implement all the methods and have an internal stack. 另一个选择是不扩展Stack而是重新实现所有方法并具有内部堆栈。 Look up "Composition vs. Inheritance" to decide which is better. 查找“组成与继承”,以确定哪个更好。

This is the only way to do it. 这是唯一的方法。 You are unable to access direct data, as it is stored in the Node as a private which is then sent to the Stack 您无法访问直接数据,因为直接数据作为私有存储在节点中,然后被发送到堆栈

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM