更改 和 对象的类.(其他的废话?

Change the class of and object. (Other aproachs?)

本文关键字:其他 对象 更改      更新时间:2023-10-16

我想这样做的时候,我有几种情况。这可能是一个例子:

考虑国际象棋游戏的可能实现。我们定义了抽象类"Piece"和从中继承的类:"主教"牡丹"塔"马"女王"等

我们的牡丹

可能即将到达棋盘的尽头,并且可能需要调用该牡丹对象的方法将该对象的类别更改为"女王"、"马"或其他什么。

所以我的问题是,有没有办法在C++或Java中做到这一点?如果没有,用任何其他语言?另外,对于这种情况,还有其他方法吗?

在C++或Java等语言中,我会创建一个"Queen"或"Horse"的新实例,并将"Peon"实例替换为该新实例。

我认为您对对象的看法与对象的使用方式混淆了。 在面向对象的语言中,我们有指示对象实例的内存位置的指针:

Piece pointerToPieceObject = new Peon();

在上面的语句中,pointerToPieceObject属于"类型"Piece。 由于PeonQueen都继承自Piece,因此此指针可以指向以下任何类型的对象实例:

pointerToPieceObject = new Queen();

这是任何面向对象语言都支持的一个非常通用的概念。 这些语言之间的唯一区别是如何处理类型(例如Python与Java)。 这个概念称为多态性,可以用来做比上面的例子更花哨的事情:http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming

您可以使用装饰器模式或策略模式。

带装饰器:

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的答案中提到的另一个实例。

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();
    }
}

我看到两个简单的选择:

  1. type是一个Pice设置为Bishop/Queen/...这样您就可以轻松更改它。

  2. 只需删除Peon并创建一个新的Queen/Horse/...取而代之。我不认为对象标识在这里非常重要。

简短的回答是否定的,你不能更改对象的类。您需要将其替换为所需类的新对象。

对于泛型基本类"升级"或"进化"到更高、更定义的类的情况,您可能希望所有定义更明确的类(骑士、女王、主教)都有一个采用 Peon 类(在本例中为 Pawn)的构造函数。如果Pawn和Knight和Queen以及所有棋子都有一个共同的基础,那么在Knight/Queen/etc的构造函数中,您将可以访问该基类中的受保护变量,并且可以将Pawn克隆到下一个类中。

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);

这是您可能能够改变类的尽可能接近。