我正在制作一款国际象棋游戏,我有一个基本的"棋子"界面,我希望所有的棋子都能实现。我有一些共同的变量,每个都需要有,但我不想让getter和setter在每个类中(似乎它违背了DRY)。
我所做的被称为我的接口PieceBase,有一个具体的类叫做Piece,我有我的实际碎片从Piece扩展和实现PieceBase。但是我不希望Piece被实例化,因为它本身没有意义,而且这个方法的某些方面让我感到不安。
这通常是怎么做的?
具体来说,这是在Java中,但我不知道它在任何其他OO语言中是否不同。
为了代码重用而使用继承通常被认为是不好的做法,至少在Java和c++中是这样(参见Joshua Bloch的"Effective Java"中的参数)。通常最好使用组合(或其他形式的委托)。
在你的情况下,我会把事情完全颠倒过来,这样Piece
就是final 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
中实现一次,而不同的部分由Type
封装。如果你需要知道你在看的是什么样的作品,你不需要使用instanceof
和cast之类的,你只需要在上面实现Piece.getType()
和switch
。
这似乎很奇怪,你会想扩展Piece和实现PieceBase…但也许我没看到什么如果你使用了一个接口,所有实现它的类仍然需要定义它们自己的getter/setter。
用抽象类代替似乎更有意义?
这样它们都使用相同的getter/setter ....如果这就是你想要达到的目标。
在这种情况下,我看不到接口的值。我建议简单地用所需的通用getter和setter定义抽象类Piece,然后让你的具体类扩展Piece。
abstract class Piece { ... common stuff ...}
class Pawn extends Piece { ... pawn-specific stuff ... }
class Knight extends Piece { ... knight-specific stuff ... }
...