我正在嘗試用繼承實作一個簡單的國際象棋問題,但我發現自己陷入了困境。
對于每種型別的棋子,我都有我的抽象 Chesspiece 類和許多子類。我需要一個陣列來存盤每件可能的移動,所以我正在考慮將變數設為靜態,因為這個陣列始終相同并且獨立于實體
public class Knight extends Chesspiece{
public static final int dy = {1, 1, 2, 2, -1, -1, -2, -2};
public static final int dx = {2, -2, 1, -1, 2, -2, 1, -1};
}
有點像這樣,但后來在我的邏輯中我只有實體而不知道它的子型別,所以我無法訪問這個變數。
我想也許我可以在 Chesspiece 類中以某種方式宣告一個抽象變數或其他東西,然后在每個子類中覆寫它的值。但是經過搜索我發現java不允許靜態繼承。
所以我想知道這個問題的最佳解決方案是什么。我非常熱衷于學習好的概念編程,所以每次我寫出更好的代碼。我雖然有可行的解決方案(不使變數靜態),但對于這個問題,它們似乎并不正確或優雅。任何幫助表示贊賞。
uj5u.com熱心網友回復:
我想也許我可以在 Chesspiece 類中以某種方式宣告一個抽象變數或其他東西,然后在每個子類中覆寫它的值。但是經過搜索我發現java不允許靜態繼承。
這里有幾件事要糾正:
- 首先,你不能有抽象變數(我假設你的意思是欄位)。欄位不參與繼承,因此它們不能在一個類中宣告,然后在另一個類中“實作”。
- 其次,靜態和抽象不能并存。它們是完全不同的東西。所以,這個說法是不合邏輯的。
正確的做法是將抽象方法添加到基類或介面中。例如,假設您的Chesspiece類是抽象的,請將其添加到那里:
abstract class Chesspiece {
// ...
abstract int[] getDx();
abstract int[] getDy();
// ...
}
現在,擴展的非抽象類Chesspiece必須提供實作:
class Knight extends Chesspiece{
private static final int dy = {1, 1, 2, 2, -1, -1, -2, -2};
private static final int dx = {2, -2, 1, -1, 2, -2, 1, -1};
@Override int[] getDy() { return dy; }
@Override int[] getDx() { return dx; }
}
如果你這樣做,每次都回傳相同的陣列實體。但是,這不一定是可取的,因為它允許Knight更改實體的內部狀態:
Knight robin = new Knight();
System.out.println(robin.getDx()[0]); // 2
Knight galahad = new Knight();
galahad.getDx()[0] = 42;
System.out.println(galahad.getDx()[0]); // 42.
System.out.println(robin.getDx()[0]); // 42 !?
To get around this, don't return the same instance each time: either declare the array inside the getter:
@Override int[] getDx() {
return new int[] {2, -2, 1, -1, 2, -2, 1, -1};
}
Knight robin = new Knight();
System.out.println(robin.getDx()[0]); // 2
Knight galahad = new Knight();
galahad.getDx()[0] = 42;
System.out.println(galahad.getDx()[0]); // 2
System.out.println(robin.getDx()[0]); // 2
Alternatively, copy the array in the getter:
@Override int[] getDx() {
return Arrays.copyOf(dx, dx.length);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/453143.html
