1

可能重复:
这里的 instanceof 检查有什么问题吗?

我有这个代码

public static int getNumberOfOwned(Player owner, String type){
    int count = 0;      
    for (Field f: board.fieldList)
        if (type == "Shipping" && f instanceof Shipping) 
            if (((Shipping)f).getOwnedBy() == owner)
                count++;
        else if (type == "Brewery" && f instanceof Brewery) 
            if (((Brewery)f).getOwnedBy() == owner)
                count++;
    return count;
}

我不认为这是非常优雅和未来的证明。我怎样才能避免那些 instanceof 运算符。

4

8 回答 8

2

您始终可以使用枚举,并使用Field返回类型的方法。在这里,我将进一步推测您不想更新某些类型的计数,因此枚举也被“装饰”了一个布尔值,表示:

enum FieldType {
    SHIPPING(true),
    BREWERY(true),
    NOTME(false);

    private final boolean countUpdate;

    FieldType(boolean countUpdate) { this.countUpdate = countUpdate; }
    public boolean mustUpdateCount() { return countUpdate; }
};

abstract class Field {
    protected final FieldType type;
    protected Field(FieldType type) { this.type = type; }
    public final FieldType getType() { return type; }
    public final boolean mustUpdateCount() { return type.mustUpdateCount(); }
}

class Brewery implements Field {
    Brewery() {
        super(BREWERY);
    }
}

并在您的代码中:

FieldType expectedType = Enum.valueOf(type.toUpperCase());

for (Field f: board.fieldlist) {
    if (field.getType() != expectedType)
        continue;
    if (!f.getOwnedBy().equals(owner))
        continue;
    // Correct type, owned by the correct guy:
    // check that we must update; if so, update
    if (expectedType.mustUpdateCount())
        count++;
}
于 2013-01-06T23:37:33.447 回答
1

由于ShippingBrewery派生自FieldField因此可以提供一个告诉您其类型的 getter,例如getFieldType(). 当ShippingBrewery被实例化时,它们会设置适当的值,或者您将它们getFieldType()抽象化并拥有ShippingBrewery实现它们。

于 2013-01-06T23:38:01.623 回答
1

Shipping.class将或传递Brewery.class给您的函数,而不是代表该类的字符串,并检查您的 Field 是否属于该类:

public static int getNumberOfOwned(Player owner, Class<? extends Field> type){
    int count = 0;      
    for (Field f: board.fieldList) {
        if (type.isInstance(f) && f.getOwnedBy() == owner) {
            count++;
        }   
    }
    return count;
}
于 2013-01-06T23:41:09.590 回答
1

最好的解决方案是使用访问者模式来解决这个问题,你可以在这里查看:访问者模式

至少它是处理问题的面向对象的方式,但它肯定需要比您当前的解决方案更多的编码。

于 2013-01-06T23:45:12.373 回答
0

将“ isType(String type)”方法添加到字段。就此而言,也将“ isOwnedBy(String owner)”添加到 Field 中。

for (Field f: board.fieldList)
    if (f.isType(type) && f.isOwnedBy(owner))
        count++;
return count;
于 2013-01-06T23:38:50.730 回答
0

首先建议您使用“==”运算符来测试对象的相等性,这在大多数情况下都是错误的,在这种情况下肯定是错误的:)

如果您想确定一个对象是否属于特定类型,您可以使用 instanceof 运算符,查看它们是否具有相同的类引用(在这里您可以使用“==”运算符)或尝试强制转换并检查异常,最后一个选项更像是一种幻想,因为在现实世界中你不应该尝试这个。

我不太确定你要做什么,但你绝对可以定制你的对象以避免 instanceof/class/cast 的东西,比如:

class Foxtrot implements Sub {
    private  SubType type = SubType.ATACK;

    public SubType getType() {
        return type;
    }
}

interface Sub {
    enum SubType{ ATACK, BOOMER }

    public SubType getType();
}

您可以将对象视为 Sub 接口的实现,并使用他们的 getType() 方法检查它们是什么类型,它应该几乎可以工作。

于 2013-01-06T23:47:09.030 回答
-1

你应该重写这段代码

1) 类字段添加方法getType();

2)代码:

public static int getNumberOfOwned(Player owner, String type){
  int count = 0;      
  for (Field f: board.fieldList){
    if (f.getType.equals(type)&& f.getOwnedBy().equesl(owner))
    count++;
  }
  return count;

}

于 2013-01-06T23:42:27.763 回答
-1

string getTypeString()创建 Field 的属性,并避免使用一堆 if 语句(检查)使type.equals(f.getTypeString())getOwnedBy 成为 Field 的属性,并且不要使用强制转换。(没有所有者的字段可以返回 null)

于 2013-01-06T23:43:09.540 回答