当我想这样做时,我遇到过几种情况。这可能是一个例子:
考虑国际象棋游戏的可能实现。我们定义了抽象类 'Piece' 和继承自它的类:'bishop' 'peon' 'tower' 'horse' 'queen' 等
我们可能让我们的 peon 即将到达棋盘的尽头,并且可能需要调用该 peon 对象的方法来将该对象的类更改为“Queen”、“horse”或其他任何东西。
所以我的问题是,有没有办法在 C++ 或 Java 中做到这一点?如果没有,用任何其他语言?另外,一般情况下还有其他方法吗?
当我想这样做时,我遇到过几种情况。这可能是一个例子:
考虑国际象棋游戏的可能实现。我们定义了抽象类 'Piece' 和继承自它的类:'bishop' 'peon' 'tower' 'horse' 'queen' 等
我们可能让我们的 peon 即将到达棋盘的尽头,并且可能需要调用该 peon 对象的方法来将该对象的类更改为“Queen”、“horse”或其他任何东西。
所以我的问题是,有没有办法在 C++ 或 Java 中做到这一点?如果没有,用任何其他语言?另外,一般情况下还有其他方法吗?
在像 C++ 或 Java 这样的语言中,我会创建一个新的“Queen”或“Horse”实例,并用那个新实例替换“Peon”实例。
我认为您对对象的想法与对象的使用方式相混淆。在面向对象的语言中,我们有指示对象实例的内存位置的指针:
Piece pointerToPieceObject = new Peon();
在上面的语句中,pointerToPieceObject是 "type" Piece。因为Peon和Queen都继承自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);
当您提前计划时,您可以使用 strategy它仍然没有真正改变类:
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();
}
}
我看到两个简单的选择:
让type一个字段设置为// ...Pice的实例(可能是单例,例如实现为枚举),这样您就可以轻松更改它。BishopQueen
只需删除Peon并在其位置创建一个新的Queen/ Horse/... 即可。我不认为对象身份在这里非常重要。
简短的回答是否定的,您不能更改对象的类。您需要将其替换为所需类的新对象。
对于通用的基本类“升级”或“演变”到更高、更定义的类的情况,您可能希望所有定义更明确的类(Knight、Queen、Bishop)都有一个采用 Peon 类的构造函数,在这种情况下,典当。如果 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);
这与您可能能够更改班级一样接近。