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

枚举

枚举允许您创建一组优化的通用类型的单例实例,这些实例也可以定义行为,但它们不能很好地支持覆盖/实现特定于类型的行为,因为您最终必须检查当前实例是哪个枚举实施变化。当您真的需要多个游戏(一个白王和一个黑王,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

如果实例数量有限且已定义,请使用枚举。

在这种情况下,显然有定义数量的片段,所以使用枚举。

请注意,枚举可以像常规类一样具有方法,因此枚举不必只是“值”,它们可以做一些事情。

我不会试图在你的枚举中塞进太多东西,事实上我会命名它PieceType以明确它代表什么,并且可能有一个类Piece,它是一个片段的实例,它有一个PieceType、一个位置(棋盘正方形)和一种颜色。

于 2013-08-17T04:01:15.817 回答
0

主要区别在于子类集是开放式的:您或其他使用您的代码的人可以在不破坏旧代码的情况下创建新的子类。枚举则相反:其他人无法向您的枚举添加新项目,甚至您(代码的维护者)也无法在不仔细检查每个 switch-case 语句的情况下添加新的枚举常量。

因此,如果您不希望将新项目添加到集合中,请使用枚举。否则使用子类。这并不意味着子类更好:如果您知道选项集是封闭的,那么您不应该使用子类。如果你这样做了,你会发现自己正在编写if (... instanceof ...)链!

如果使用枚举,您发现自己在语句中添加了新case的 s switch(或者您可以预料到),然后切换到子类。如果使用子类,您会发现自己正在编写instanceof链,然后切换到枚举。

于 2013-08-17T07:37:15.650 回答