如何避免这种情况下的 instanceof 使用?

huangapple go评论79阅读模式
英文:

How to avoid instanceof from this kind of case?

问题

以下是翻译好的代码部分:

在Player.java中,我当前的代码如下所示:

public boolean canPutCard(Card card) {
    if (!handCards.contains(card)) {
        return false;
    }
    if (card instanceof ActivableCard) {
        boolean hasEmpty = false;
        int i = card instanceof CharacterCard ? 0 : 1;
        for (int j = 0; j < fieldCards[i].length; ++j) {
            if (fieldCards[i][j] == null) {
                hasEmpty = true;
            }
        }
        if (!hasEmpty) {
            return false;
        }
    }
    return (card instanceof LandCard && !hasPutLandCard) || (card instanceof PoweredCard
            && ((PoweredCard) card).getPowerNeeded() <= currentElementValue[card.getElementType().ordinal()]);
}

我想避免在这里使用多个 instanceof,因为它们被称为“代码异味”,而是使用多态性来代替。所以我可以将它重写如下:

public boolean canPutCard(LandCard card) {
    return !hasPutLandCard;
}

public boolean canPutCard(PoweredCard card) {
    return card.getPowerNeeded() <= currentElementValue[card.getElementType().ordinal()];
}

private boolean canPutCard(int i, PutableCard card) {
    boolean hasEmpty = false;
    for (int j = 0; j < fieldCards[i].length; ++j) {
        if (fieldCards[i][j] == null) {
            hasEmpty = true;
        }
    }
    return hasEmpty;
}

public boolean canPutCard(PutableCard card) {
    return canPutCard(1, card);
}

public boolean canPutCard(CharacterCard card) {
    return canPutCard(0, card);
}

public boolean canPutCard(Card card) {
    return handCards.contains(card);
}

类:

抽象类 SkillCard 扩展自 Card同时实现 PoweredCard 接口
类 CharacterCard 扩展自 Card同时实现 PoweredCard 和 PutableCard 接口
类 LandCard 扩展自 Card

但是,肯定不能正常工作,因为它没有检查所有情况...

在这种情况下,是否可能避免使用 instanceof 而改用多态性呢?

英文:

My current code in Player.java is like this:

    public boolean canPutCard(Card card) {
        if (!handCards.contains(card)) {
            return false;
        }
        if (card instanceof ActivableCard) {
            boolean hasEmpty = false;
            int i = card instanceof CharacterCard ? 0 : 1;
            for (int j = 0; j &lt; fieldCards[i].length; ++j) {
                if (fieldCards[i][j] == null) {
                    hasEmpty = true;
                }
            }
            if (!hasEmpty) {
                return false;
            }
        }
        return (card instanceof LandCard &amp;&amp; !hasPutLandCard) || (card instanceof PoweredCard
                &amp;&amp; ((PoweredCard) card).getPowerNeeded() &lt;= currentElementValue[card.getElementType().ordinal()]);
    }

I want to avoid using of multiple instanceofs here because of what they call it "code smells" and use polymorphism instead. So what I can do is to rewrite it to be like this:

    public boolean canPutCard(LandCard card) {
        return !hasPutLandCard;
    }

    public boolean canPutCard(PoweredCard card) {
        return card.getPowerNeeded() &lt;= currentElementValue[card.getElementType().ordinal()];
    }

    private boolean canPutCard(int i, PutableCard card) {
        boolean hasEmpty = false;
        for (int j = 0; j &lt; fieldCards[i].length; ++j) {
            if (fieldCards[i][j] == null) {
                hasEmpty = true;
            }
        }
        return hasEmpty;
    }

    public boolean canPutCard(PutableCard card) {
        return canPutCard(1, card);
    }

    public boolean canPutCard(CharacterCard card) {
        return canPutCard(0, card);
    }

    public boolean canPutCard(Card card) {
        return handCards.contains(card);
    }

classes:

abstract class SkillCard extends Card implements PoweredCard
class CharacterCard extends Card implements PoweredCard, PutableCard
class LandCard extends Card

But, surely it won't work because it doesn't check every cases..

Is it possible to avoid instanceof and use polymorphism instead in this case?

答案1

得分: 1

// Instanceof操作符通常可以通过充分依赖Java虚拟分派来替代。将决策逻辑移动到Card类中,像这样:

public abstract boolean canPutCard(Player player);

然后在Card子类中实现相应的逻辑例如

class LandCard extends Card {
    @Override public boolean canPutCard(Player player) {
         return !player.hasPutLandCard() && player.handContains(this);
    }
}

class CharacterCard extends Card implements PoweredCard, PutableCard {
    @Override public boolean canPutCard(Player player) {
         return !player.hasEmptyCharacterCardField() && player.handContains(this);
    }
}
// ... 以此类推。Player类将需要必要的查询方法。
英文:

Instanceof operator can usually be replaced with proper reliance on java virtual dispatch. Move decision logic to Card class, like this

public abstract boolean canPutCard(Player player);

And then implement appropriate logic in Card subclasses like:

class LandCard extends Card {
    @Override public boolean canPutCard(Player player) {
         return !player.hasPutLandCard() &amp;&amp; player.handContains(this);
    }
}

class CharacterCard extends Card implements PoweredCard, PutableCard {
    @Override public boolean canPutCard(Player player) {
         return !player.hasEmptyCharacterCardField() &amp;&amp; player.handContains(this);
    }
}

... and so on. Player class will need to have required query methods.

huangapple
  • 本文由 发表于 2020年4月9日 03:20:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/61108392.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定