3

私はそれをしたいときにいくつかの状況がありました。これは例です:

チェス ゲームの可能な実装を考えてみましょう。抽象クラス 'Piece' とそれを継承するクラスを定義します: 'bishop' 'peon' 'tower' 'horse' 'queen' など

peon がボードの最後に到達しようとしている可能性があり、その peon オブジェクトに対して呼び出されたメソッドがそのオブジェクトのクラスを「Queen」、「horse」などに変更する必要がある場合があります。

私の質問は、C++ または Java でそれを行う方法はありますか? そうでない場合、他の言語で?また、一般的にこの状況に対する他のアプローチはありますか?

4

6 に答える 6

10

C++ や Java などの言語では、「Queen」または「Horse」の新しいインスタンスを作成し、「Peon」インスタンスをその新しいインスタンスに置き換えます。

于 2012-06-29T13:02:19.463 に答える
2

オブジェクトについてのあなたの考えは、オブジェクトの使用方法と混同されていると思います。オブジェクト指向言語では、オブジェクト インスタンスのメモリ位置を示すポインタがあります。

Piece pointerToPieceObject = new Peon();

上記のステートメントでpointerToPieceObjectは、 は "type"Pieceです。PeonQueenは両方とも から継承するためPiece、このポインタは次のいずれかのタイプのオブジェクト インスタンスを指すことができます。

pointerToPieceObject = new Queen();

これは、あらゆるオブジェクト指向言語でサポートされている非常に一般的な概念です。これらの言語の唯一の違いは、タイピングの処理方法です (Python と Java など)。この概念はポリモーフィズムと呼ばれ、上記の例よりもはるかに手の込んだことを行うために使用できます

于 2012-06-29T13:08:36.780 に答える
0

デコレータ パターンまたは戦略パターンを使用できる場合があります。

デコレータあり:

interface ChessPiece {
    Set<Move> getPossibleMoves();
    Image getAppearance();
}

class Pawn implements ChessPiece {
    ...
}

class Decorator implements ChessPiece {
    ChessPiece decorated;

    public Decorator(ChessPiece decorated_) {
        this.decorated = decorated_;
    }

    @override
    Set<Move> getPossibleMoves() {
        Set<Move> result = decorated.getPossibleMoves();
        // alter result
        return result;
    }
}

必要に応じて、Pawnインスタンスをインスタンスに置き換えDecoratedます。 そのため、 OpenSause の回答で述べたように、1 つのインスタンスを別のインスタンスに置き換える必要があります。

ChessPiece pawn = new Pawn;
...
pawn = new Decorated(pawn);

前もって計画するときは、戦略を使用できますが、実際にはクラスを変更していません:

interface PossibleMovesStrategy {
    Set<Move> getPossibleMoves();
}

interface AppearanceStrategy {
    Image getAppearance();
}

class ChangingChessPiece extends ChessPiece {
    PossibleMovesStrategy posMoves;
    AppearanceStrategy appearance;

    @override
    Set<Move> getPossibleMoves() {
        return posMoves.getPossibleMoves();
    }

    @override
    Image getAppearance() {
        return appearance.getAppearance();
    }
}
于 2012-06-29T13:01:28.753 に答える
0

2 つの簡単な代替手段があります。

  1. / /のインスタンス(おそらくシングルトン、たとえば列挙型として実装されたもの)に設定されtypeフィールドになります...このようにして、簡単に変更できます。PiceBishopQueen

  2. を削除して、その場所にPeon新しいQueen/ Horse/... を作成するだけです。ここでは、オブジェクトの同一性はそれほど重要ではないと思います。

于 2012-06-29T13:04:06.917 に答える
0

オブジェクトのクラスを変更することはできません。目的のクラスの新しいオブジェクトに置き換える必要があります。

于 2012-06-29T13:04:07.517 に答える
0

一般的な基本クラスが、より高度でより定義されたクラスに「アップグレード」または「進化」する状況では、より定義されたすべてのクラス (Knight、Queen、Bishop) に、Peon クラスを取るコンストラクターを持たせることができます。この場合はポーンです。ポーン、ナイト、クイーン、およびすべてのピースに共通のベースがある場合、ナイト/クイーンなどのコンストラクターで、そのベース クラスにある保護された変数にアクセスし、ポーンを次のクラスに複製できます。

class Pawn extends ChessPiece {...}

class Queen extends ChessPiece {
    public Queen(Pawn p) {
        // DON'T accept a ChessPiece unless you want
        // knights or rooks to become queens.

        // copy p's variables here
    }
}

ChessPiece piece= new Pawn();
// Sometime later...
if (piece is Pawn)
    piece = new Queen((Pawn)piece);

これは、おそらくクラスを変更できるようになるのと同じくらい近いです。

于 2012-06-29T15:19:14.077 に答える