如何避免子类的类型检查?

时间:2017-07-28 01:35:22

标签: java oop

我有这段代码:

public abstract class Character {
    public abstract void attack(Character victim);
    public abstract void receiveAttack(Attack attack);
}

public class CharacterA extends Character {
    public void attack(Character victim) {
        if (victim.getClass().equals(this.getClass())
            return;

        victim.receiveAttack(new Attack(BASE_DMG));
    }
}

这个想法是一个角色可以攻击和接收来自其他角色的攻击,但是它不能接收来自其自己类的角色的攻击(CharacterA不能攻击另一个角色,但可以攻击角色B或接受攻击CharacterB)。

我知道检查一个物体的类型是一种难闻的气味,通常是由于设计不好造成的,所以问题是我怎么能改变设计所以我不必检查对象类型?

修改

该类实际上并未命名为Character,该名称只是为了简化示例。

没有球队。 CharacterA可以攻击任何不是Character的其他CharacterA

最终编辑

谢谢大家,我通过使用访问者模式解决了这个问题。

2 个答案:

答案 0 :(得分:1)

一个非常简单的解决方案/解决方法可能只有一个类,每个Character对象都有一个名为String的{​​{1}}字段或类似的东西。对于A团队中的角色,请将该字段设置为characterTeam"A"。对于B小组,请将该字段设置为"ATeam""B"。然后在"BTeam"方法中比较他们的characterTeam String

另外,我建议不要使用名为attack的类,因为这可能会干扰Character的包装类,也称为char

答案 1 :(得分:0)

您可以通过向声明为获取特定子类的实例的每个子类添加重载攻击方法,并使此方法成为无操作或打印警告来实现此目的。

对于CharacterA,签名将是

public void attack(CharacterA victim)

但是,只有在使用特定类型而不是基本字符类型声明子类实例时,这才有效。

class Character
{
    public void attack(Character victim)
    {
        System.out.println(getClass() + " attacking " + victim.getClass());
        victim.receiveAttack(new Attack());
    }

    public void receiveAttack(Attack attack) {}
}

class CharacterA extends Character
{
    public void attack(CharacterA victim)
    {
        System.out.println(getClass() + " cannot attack " + victim.getClass());
    }
}

class CharacterB extends Character
{
    public void attack(CharacterB victim)
    {
        System.out.println(getClass() + " cannot attack " + victim.getClass());
    }
}

class Attack
{
}

public class Test
{
    public static void main(String[] args)
    {
        CharacterA a = new CharacterA();
        CharacterB b = new CharacterB();

        a.attack(a);
        a.attack(b);
        b.attack(a);
        b.attack(b);

        // redeclare a & b to have the base type
        Character c = a;
        Character d = b;

        c.attack(c);
        c.attack(d);
        d.attack(c);
        d.attack(d);
    }
}

输出:

    class CharacterA cannot attack class CharacterA
    class CharacterA attacking class CharacterB
    class CharacterB attacking class CharacterA
    class CharacterB cannot attack class CharacterB
    class CharacterA attacking class CharacterA
    class CharacterA attacking class CharacterB
    class CharacterB attacking class CharacterA
    class CharacterB attacking class CharacterB