如何避免instanceof?

时间:2013-01-06 23:32:17

标签: java

  

可能重复:
  Anything wrong with instanceof checks here?

我有这段代码

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

我不认为这是非常优雅和未来的证据。我怎样才能避免那些运营商的实例。

8 个答案:

答案 0 :(得分: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++;
}

答案 1 :(得分:1)

由于ShippingBrewery来自FieldField可以提供一个告诉你类型的getter,类似于getFieldType()。在实例化ShippingBrewery时,他们会设置适当的值,或者您将getFieldType()抽象为摘要,并让ShippingBrewery实施它们。

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

最好的解决方案是使用访问者模式解决此问题,您可以在此处查找:Visitor pattern

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

答案 4 :(得分:0)

向Field添加“isType(String type)”方法。就此而言,也要向Field添加“isOwnedBy(String owner)”。

for (Field f: board.fieldList)
    if (f.isType(type) && f.isOwnedBy(owner))
        count++;
return count;

答案 5 :(得分: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()方法检查它们是什么类型,它应该可以工作。

答案 6 :(得分:-1)

您应该重写此代码

1) 类字段 add方法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;

}

答案 7 :(得分:-1)

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