2011-10-26 36 views
0

我正在製作一款國際象棋遊戲,並且我有一個基本的'piece'界面,我希望所有部分都可以實現。我有一些共同的變量,每個變量都需要有,但是我不想讓每個類中都有getter和setter(看起來反正幹掉它)。如何在界面中實現getter/setter?

我所做的是稱爲我的界面PieceBase,有一個具體的類叫Piece,我有我的Piece實際片段範圍和實現PieceBase。我不希望Piece能夠被實例化,因爲它本身沒有意義,而且這種方法有些讓我感到不安。

這是如何正常完成的?

具體來說,這是用Java編寫的,但我不知道它是否與其他OO語言不同。

+0

也許抽象而不是界面? – iCantSeeSharp

回答

2

它通常被認爲是不好的做法,至少在Java和C++,使用繼承了代碼重用的目的(見約書亞布洛赫的「有效的Java」的論點)。代之以使用構圖(或某種其他形式的委託)通常更好。

在你的情況下,我把周圍的事物完全,使得Piecefinal class採取簡單的enum代表片的類型是:

public final class Piece { 

    public static enum Type { 
     PAWN { 
      List<Move> getLegalMoves(Color c, Location l) { /* ... */ } 
     }, 
     BISHOP { /* ... */ }, 
     KNIGHT { /* ... */ }, 
     ROOK { /* ... */ }, 
     QUEEN { /* ... */ }, 
     KING { /* ... */ }; // i hope i didn't forget anything :P 

     abstract List<Move> getLegalMoves(Color c, Location l); 
     // ... etc. 
    } 

    private final Type type; 
    private final Color color; 
    private Location location; 

    public Piece(Type type, Color color, Location location) { 
     this.type = type; 
     this.color = color; 
     this.location = location; 
    } 

    public List<Move> getLegalMoves() { 
     return type.getLegalMoves(color, location); 
    } 

    // ... etc. 
} 

因此,所有的邏輯的共同跨越所有對象是在Piece中實施一次,不同部分由Type封裝。如果你需要知道你正在看什麼樣的作品,那麼你不需要使用instanceof或者其他任何東西,你只需要實現Piece.getType()switch就可以了。

+0

我同意只爲代碼重用使用繼承是不好的做法。然而,這個特殊的例子看起來像是一個文本書的例子,它適用於繼承的地方:(一個Bishop真的是「一個」一塊,並且在一個抽象的片段上傳遞和調用一個抽象的getLegalMoves()正是多態性意味着什麼)對於我來說,switch語句的使用暗示着可能有更多的面向對象的設計。 –

+0

啊,但我* *使用繼承!可以這樣想:'enum Type'的每個值實際上是* anonymous *'final class'的一個單例實例,它實現了'Type'的接口。這些類在'Piece'中使用多態(參見'getLegalMoves()')。還要注意,這種方法有意防止客戶定義附加的「Piece」類型;在這個意義上說,這與斯卡拉的「密封特質」和「case class」相結合。 – mergeconflict

+0

非常酷。我非常喜歡這個用Java來模擬'密封特質''case class'的習慣用法。我可能會竊取這個想法並自己使用它。謝謝! (儘管如此,在這個特殊的例子中,我仍然傾向於使用Piece類的普通舊式繼承。) –

1

看起來很奇怪,你會想擴展Piece和Implement PieceBase ...但也許我沒有看到什麼東西。如果你使用了一個接口,那麼實現它的所有類將仍然需要定義他們自己的getter/setter。

這樣做似乎有意義,而不是抽象類?

這樣他們都使用相同的getters/setters ....如果這就是你想要完成的。

+0

我嘗試了一個抽象類,但是我無法將Piece傳遞給一個方法。例如 movePiece(Piece piece)只能用於一個接口或一個具體的類,但是抽象類我必須爲movePiece(典當典當)movePiece(Rook rook)製作6種不同的方法 – RankWeis

+0

這應該適用於一個抽象類。如果你像你說的那樣定義它,movePiece(Piece piece)...並將你的作品實例化爲Piece rook = new Rook(); ,它應該很好地接受它。當然,我不確定爲什麼你會有Piece定義你的移動,因爲每件應該有不同的移動功能。 – dispake

+0

我會試一試。這是從棋盤上的一個位置移動到另一個位置,運動在單個Piece實例中分別處理 – RankWeis

0

在這種情況下,我看不到接口的值。我建議簡單地定義抽象類Piece與所需的通用getter和setter,然後讓你的具體類擴展Piece。

abstract class Piece { ... common stuff ...} 
class Pawn extends Piece { ... pawn-specific stuff ... } 
class Knight extends Piece { ... knight-specific stuff ... } 
... 
+0

請參閱我對dispake的回答的評論,我相信我會遇到同樣的問題 – RankWeis

+0

dispake的回答基本上與我的相同。 –

+0

一個問題是爲什麼你的Piece的movePiece方法採取Piece參數。這意味着涉及兩個部分:「this」部分和傳入的部分。 –