可接受的instanceof使用

sca*_*ter 14 java instanceof

我是Java的新手并且在设计问题上苦苦挣扎.我知道使用instanceof可能表示设计缺陷,我理解经常给出的Animal/Dog/Cat类作为例子,替换bark()meow()使用makenoise()等.

我的问题是,如果我需要根据子类的类型调用没有相应方法的方法,那么什么是合理的设计?例如,如果我想调用一个新方法,biteleash()如果该类是a,Dog但如果它是一个什么都不做,该Cat怎么办?

我确实考虑biteleash()Animal什么都不做,并且覆盖它Dog,但是有许多这样的方法,所以它似乎是一个笨重的解决方案.类似地,如果调用者需要根据它所拥有的子类做一些不同的事情,例如.如果子类是一个终止Cat?是instanceof可以接受的这里,还是有更好的办法?

public class Animal {

    String name;

    public Animal(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void makeNoise() {
        System.out.println("Some noise for a generic animal!");
    }

}

public class Cat extends Animal {

    public Cat(String name) {
        super(name);
    }

    @Override
    public void makeNoise() {
        System.out.println("Meow");
    }
}

public class Dog extends Animal {

    public Dog(String name) {
        super(name);
    }

    @Override
    public void makeNoise() {
        System.out.println("Woof");
    }

    public void biteLeash() {
        System.out.println("Leash snapped!");
    }
}

import java.util.Random;

public class CodeExample {


    public static void main(String[] args) {

        Animal animal = getSomeAnimal();
        System.out.println("My pet is called " + animal.getName());
        animal.makeNoise();

        if (animal instanceof Dog) {
            Dog dog = (Dog) animal;
            dog.biteLeash();
            // do lots of other things because animal is a dog
            // eg. sign up for puppy training lessons
        }
    }

    private static Animal getSomeAnimal() {
        Animal animal;
        Random randomGenerator = new Random();
        int randomInt = randomGenerator.nextInt(100);      
        if (randomInt < 50) {
            animal = new Dog("Rover");
        }
        else {
            animal = new Cat("Tiddles");
        }
        return animal;
    }
}
Run Code Online (Sandbox Code Playgroud)

Bat*_*eba 10

组合将在这里帮助您,并且在Java中是惯用的.

设计一个名为的界面,比如说Leashable.这是由a实现的Dog,但不是a Cat.

instanceof您可以尝试使用引用Leashable来查看它是否由您的特定对象实现,而不是使用.

在我看来,你应该继续以类似的方式:建立一个NoisyAnimal界面.也许就像Noisy为什么噪音只与动物有关?Parrot比如说,实现这一目标将会产生超出Cat或的技术挑战Dog.良好的可维护程序隔离了复杂性和组合区域,可帮助您实现这一目标

  • @tim我认为`try {Leashable leDog =(Leashable)aniDog} catch(..){...}`,在这种情况下`instanceof`绝对是一个更好的选择.你仍然需要做一个明确的演员表,但是预测处理是一个反模式 (4认同)
  • 检查`instanceof`然后尝试转换为接口并支持捕获ClassCastExceptions更容易. (3认同)

bre*_*ine 5

你不应该使用具体的类.实例本身不是问题.它存在是有原因的.您应该使用松散耦合的接口,即您的代码不应该依赖于具体的类实现.我建议你尽可能使用接口(即IAnimal而不是Animal)

你应该使用像ILeashable这样的界面(对于名字来说有点荒谬),而不是检查Dog,然后:

public interface ILeashable {
   //add other methods which is connected to being on a leash
   void biteLeash();
}

class Dog implements ILeashable {...}
Run Code Online (Sandbox Code Playgroud)

也没有一种方法可以做到这一点,有一些模式,即装饰器或依赖倒置,在这种情况下可能会帮助你.