2011-10-26 8 views
0

私はチェスゲームを作っています。私はすべての部分を実装したいという基本的な「ピース」インターフェースを持っています。それぞれに必要な共通変数がいくつかありますが、各クラスにgetterとsetterを作成する必要はありません(とにかくDRYに反するようです)。インターフェイスにゲッター/セッターを実装するにはどうすればよいですか?

インターフェイスのPieceBaseと呼ばれる具体的なクラスをPieceといい、Pieceから実際のピースの範囲を持ち、PieceBaseを実装しています。私はPieceをインスタンス化することは望ましくありません。なぜなら、それ自体は意味をなさないので、このメソッドの何かが私を不安にさせるからです。

これはどのようにして正常に行われますか?

これはJavaで書かれていますが、他のOO言語と異なるかどうかはわかりません。

+0

おそらくインターフェイスではなく抄録を作成しますか? – iCantSeeSharp

答えて

2

一般的には、(引数についてジョシュア・ブロックの「効果的なJavaの」を参照してください)コードの再利用のために継承を使用するには、少なくともJavaとC++で、悪い習慣と考えられています。代わりにの構成(または他の形式の委任)を使用する方が良いでしょう。あなたのケースでは

私は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で1回実装され、異なる部分はTypeによってカプセル化されます。あなたが見ている作品の種類を知る必要がある場合は、instanceofとキャストなどを使う必要はなく、Piece.getType()switchを実装するだけです。

+0

コードの再利用のためだけに継承を使用することは悪い習慣であることに同意します。しかし、この特定のケースは、継承を使用するのが適切であるテキストブックの例のようです:(実際に "is-a" Pieceであり、抽象的なPiece上のabstract getLegalMoves()を渡して呼び出すことは、 )私にとっては、switch文の使用は、よりオブジェクト指向の代替設計が可能であるというヒントです。 –

+0

ああ、私は相続を使っています! 'enum Type'の各値は実際に' Type'のインタフェースを実装する* anonymous * 'final class'の* singletonインスタンス*です。これらのクラスは、 'Piece'(' getLegalMoves() '参照)で多態的に使用されます。また、このアプローチは意図的に追加の 'Piece'型がクライアントによって定義されるのを防ぎます。その意味では、「ケースクラス」と組み合わされたScalaの封印された特性に似ています。 – mergeconflict

+0

非常にクールです。私はJavaで 'sealed trait' /' case class'をエミュレートするこのイディオムが好きです。私はおそらくそのアイデアを盗み、それを自分で使うだろう。ありがとう! (しかし、この特定の例では、Pieceクラスの普通の継承を使用する傾向があります。) –

1

PieceとImplement PieceBaseを拡張したいと思うのは変だと思いますが、多分私は何かを見ていません。インターフェイスを使用した場合、それを実装するすべてのクラスは、独自のgetter/setterを定義する必要があります。

代わりに抽象クラスを作るのが理にかなっているようですね。

彼らはすべて同じゲッター/セッターを使用しています....これがあなたが達成しようとしているものです。

+0

私は抽象クラスで試しましたが、私はPieceをメソッドに渡すことができませんでした。したがって、たとえば movePiece(ピースピース)は、インターフェイスまたは具体的なクラスでのみ動作しますが、抽象クラスではmovePiece(Pawn pawn)に6つの異なるメソッドを作成する必要がありますmovePiece(Rook rook) – RankWeis

+0

抽象クラス。あなたが言ったように定義した場合、movePiece(Piece piece)...ピースrook = new Rook(); 、それはそれをうまく受け入れる必要があります。もちろん、私はあなたがピースにあなたの移動を定義させる理由は分かりません。なぜなら、それぞれのピースは異なる移動機能を持つべきだからです。 – 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

ディスパークの答えについての私のコメントを参照してください、私は同じ問題に実行すると信じて – RankWeis

+0

ディスパークの答えは基本的に私と同じです。 –

+0

1つの質問は、PieceのmovePieceメソッドがPiece引数を取る理由です。それは2つの作品が関係していることを意味します:「この」作品と渡された作品。 –

関連する問題