2

私がチェスのゲームを作っているとしましょう。Piece() の基本クラスを持つ方が効果的でしょうか? 作品の種類ごとにサブクラスがあります。

または、列挙型

enum Piece{
King,
Queen,
Knight,
etc;
}

また、データを絞り込むときによくある問題にも直面します。

GameObjects
Piece extends GameObjects

ここでやめて、個々のプロパティでオブジェクトを宣言する必要がありますか?

Piece King = new Piece("King",5,10); //just made up values, no significance.

またはそれをさらに改良して、次のようにします。

King extends Piece

次に、King Pieces をポリモーフィックな方法で処理します。

Piece king = new King("King,5,10);

ありがとう

4

3 に答える 3

1

ポリモーフィズム

ゲームのロジックをどのように構築するかによって異なりますが、共通の動作 (メソッド) と属性 (フィールド) を抽象Pieceクラスで定義し、各サブタイプに抽象メソッドを実装 (またはデフォルト メソッドをオーバーライド) させ、変化する方法に基づいて、継承されたフィールドの値を設定します。たぶん次のようなものです:

public abstract class Piece {
    protected int value;
    public int getValue() {
        return value;
    }
    public abstract boolean isValidMove(String move);
    public void move(String move) {
        //common logic here
        doMove(move);
    }
    protected abstract void doMove(String move);
}

public class King extends Piece {
    public King() {
        this.value = 20;
    }
    public boolean isValidMove(String move) {
        //specific king logic here
    }
    protected void doMove(String move) {
        //more specific king logic
    }
}

これにより、ポリモーフィズムを使用して共通のPieceAPI でさまざまな部分を定義できますが、重要な違いは各具体的な型によって処理されます。

Piece king = new King();
//...
if(king.isValidMove(move)) king.move(move);

列挙型

列挙型を使用すると、共通の型の最適化されたシングルトン インスタンスのセットを作成できます。これは動作を定義することもできますが、型固有の動作のオーバーライド/実装をうまくサポートしていません。バリエーションの実装。また、ゲームのためにそれらの倍数 (1 つの白のキングと 1 つの黒のキング、8 つの白のポーンと 8 つの黒のポーン) が本当に必要な場合でも、単一KINGまたはインスタンスしか持たないという問題が発生します。PAWN

public enum Piece {
    KING(20),
    PAWN(1);
    private int value;
    private Piece(int value) {
        this.value = value;
    }
    public int getValue() {
        return value;
    }
    public boolean isValidMove(String move) {
        switch(this) {
            case KING:
                //king specific logic
                break;
            case PAWN:
                //pawn specific logic
                break;
        }
    }
    public void move(String move) {
        if(this == KING) {
            //king specific logic
        } else if(this == PAWN) {
            //pawn specific logic
        }
    }
}

したがって、このシナリオでは列挙型はおそらくうまく機能しません。

于 2013-08-17T03:44:26.697 に答える
0

主な違いは、サブクラスのセットが無制限であることです。あなたまたはあなたのコードを使用する他の人は、古いコードを壊すことなく新しいサブクラスを作成できます。列挙型は逆です。他の人は列挙型に新しい項目を追加できません。また、コードの管理者であるあなたでさえ、すべての switch-case ステートメントを再確認しない限り、新しい列挙型定数を追加できません。

そのため、新しいアイテムがセットに追加されることが予想されない場合は、列挙型を使用してください。それ以外の場合は、サブクラスを使用してください。これは、サブクラスの方が優れているという意味ではありません。オプションのセットが限定的であることがわかっている場合は、サブクラスを使用しないでください。もしそうなら、あなたはif (... instanceof ...)チェーンを書いていることに気付くでしょう!

case列挙型を使用してステートメントに新しい を追加することに気付いた場合switch(またはそれを予測できる場合) は、サブクラスに切り替えます。また、サブクラスを使用してinstanceofチェーンを記述していることに気付いた場合は、列挙型に切り替えます。

于 2013-08-17T07:37:15.650 に答える
0

インスタンスの数が限定され定義されている場合は、列挙型を使用します。

この場合、定義された数のピースがあることは明らかなので、enum を使用します。

列挙型は通常のクラスと同じようにメソッドを持つことができるため、列挙型は単なる「値」である必要はなく、何かを行うことができることに注意してください。

私はあなたの列挙型にあまり詰め込もうとはしません。実際、それが何を表しているのかを明確にするために名前を付けPieceTypeますPiecePieceType色。

于 2013-08-17T04:01:15.817 に答える