[英]Java inheritance, how to override a method in subclass
我正在研究實習面試問題。 問題是僅使用一個以上的堆棧進行臨時存儲來實現排序的堆棧。
實現的描述:我正在擴展Stack類以實現SortedStack類。 SortedStack類的大多數方法與Stack類相同,因此我不需要實現它們。 僅推入方法被覆蓋。
在我的實現中,我將當前堆棧傳遞給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();
}
}
堆棧是java.util.Stack,如以下網址所述: http : //docs.oracle.com/javase/7/docs/api/java/util/Stack.html
首先,如果要擴展java.util.Stack
,則應為其提供基本類型。 這是錯誤的:
public class SortedStack extends Stack {...}
在這種情況下, Stack
是原始類型 。 原始類型只能與遺留代碼一起使用,因為這樣會失去類型安全性。 相反,您應該使用:
public class SortedStack extends Stack<Node> {...}
這樣做將自動使您的堆棧僅接受Node
元素。
就像我在評論中說的那樣,您應該重寫 push
方法,而不要重載它。 這意味着它必須具有與父類的push
方法完全相同的參數。 因此,它僅應采用Node
參數,僅此而已。 使用@Override
批注標記該方法,以確保您確實覆蓋了該方法,並且未超載。 如果您有其他參數或不兼容的參數類型,則編譯器將發出錯誤。
您會注意到,一旦這樣做,就必須更改方法的聲明以也返回Node
,因為這是在java.util.Stack
聲明push
方式。
因此,您的方法應為:
@Override
public Node push(Node n) {
...
}
您應該使用以下命令從main
調用它:
stack.push( new Node( 10, 1.1f ) );
由於您已經使用類型正確聲明了它,因此無需將pop
的結果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()
相同(您在代碼java.util.Stack
使用了isEmpty()
,但java.util.Stack
僅具有empty()
)。
所以實際上應該是:
while (!empty() && peek().getKey() > n.getKey() ) {
tempStack.push(pop());
}
(我對您的循環進行了一些改進,如果沒有多余的if
)。
但是,提防使用this.push()
或只是push()
來獲取主堆棧。 您可以改用super.push()
。 這樣,它將使用原始行為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
而是重新實現所有方法並具有內部堆棧。 查找“組成與繼承”,以確定哪個更好。
這是唯一的方法。 您無法訪問直接數據,因為直接數據作為私有存儲在節點中,然后被發送到堆棧
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.