如何避免Java中的instanceof check

如何避免Java中的instanceof check,java,instanceof,visitor-pattern,Java,Instanceof,Visitor Pattern,我的班级结构如下: class Thing { } abstract class Pet extends Thing { void eat(Thing thing) { // do something } } class Tiger extends Pet { void eat(Thing thing) { if (thing instanceOf Creature) // do Something

我的班级结构如下:

class Thing {
}

abstract class Pet extends Thing {
    void eat(Thing thing) {
       // do something
    }
}

class Tiger extends Pet {
    void eat(Thing thing) {
        if (thing instanceOf Creature)
             // do Something
        else
             super.eat(thing);
    }
}
我想避免子类
Tiger
中的check实例?有没有办法做到这一点?如何使用访问者模式替换此项

Thing
是一个基类。
Pet
是一个抽象类,它具有方法
eat()

子类Tiger需要eat方法的具体实现。

我可以想出几种解决方案:

  • 将检查移动到Thing:
    if(Thing.isEatable())
  • 如果不可吃,让thing抛出异常:
    尝试{eat(thing);}catch…
  • 不要以为所有的宠物都能吃东西。从宠物中移除
    吃(东西)
    方法,并将
    吃(生物)
    吃(食物)
    方法添加到
    老虎
  • 将逻辑移到
    对象
    。调用
    thing.beingEaten()
    ,并覆盖
    生物
    中的该方法,以调用
    doSomething
    而不是
    eat
  • 编辑:

    只有当对象是
    生物时,如何调用
    doOneThing()

    带有instanceof:

    class Tiger extends Pet {
        void eat (Thing thing) {
            if (thing is instanceOf Creature) {
                doOneThing();
            } else {
                doOtherThing();
            }
        }
    }
    
    class Tiger extends Pet {
        void eat(Thing thing) {
            thing.beEaten();
        }
    }
    
    class Creature extends Thing {
        void beEaten() {
            doOneThing();
        }
    }
    
    class Thing {
        void beEaten() {
            doOtherThing();
        }
    }
    
    没有instanceof:

    class Tiger extends Pet {
        void eat (Thing thing) {
            if (thing is instanceOf Creature) {
                doOneThing();
            } else {
                doOtherThing();
            }
        }
    }
    
    class Tiger extends Pet {
        void eat(Thing thing) {
            thing.beEaten();
        }
    }
    
    class Creature extends Thing {
        void beEaten() {
            doOneThing();
        }
    }
    
    class Thing {
        void beEaten() {
            doOtherThing();
        }
    }
    

    我可以想出几种解决办法:

  • 将检查移动到Thing:
    if(Thing.isEatable())
  • 如果不可吃,让thing抛出异常:
    尝试{eat(thing);}catch…
  • 不要以为所有的宠物都能吃东西。从宠物中移除
    吃(东西)
    方法,并将
    吃(生物)
    吃(食物)
    方法添加到
    老虎
  • 将逻辑移到
    对象
    。调用
    thing.beingEaten()
    ,并覆盖
    生物
    中的该方法,以调用
    doSomething
    而不是
    eat
  • 编辑:

    只有当对象是
    生物时,如何调用
    doOneThing()

    带有instanceof:

    class Tiger extends Pet {
        void eat (Thing thing) {
            if (thing is instanceOf Creature) {
                doOneThing();
            } else {
                doOtherThing();
            }
        }
    }
    
    class Tiger extends Pet {
        void eat(Thing thing) {
            thing.beEaten();
        }
    }
    
    class Creature extends Thing {
        void beEaten() {
            doOneThing();
        }
    }
    
    class Thing {
        void beEaten() {
            doOtherThing();
        }
    }
    
    没有instanceof:

    class Tiger extends Pet {
        void eat (Thing thing) {
            if (thing is instanceOf Creature) {
                doOneThing();
            } else {
                doOtherThing();
            }
        }
    }
    
    class Tiger extends Pet {
        void eat(Thing thing) {
            thing.beEaten();
        }
    }
    
    class Creature extends Thing {
        void beEaten() {
            doOneThing();
        }
    }
    
    class Thing {
        void beEaten() {
            doOtherThing();
        }
    }
    

    我可以想出几种解决办法:

  • 将检查移动到Thing:
    if(Thing.isEatable())
  • 如果不可吃,让thing抛出异常:
    尝试{eat(thing);}catch…
  • 不要以为所有的宠物都能吃东西。从宠物中移除
    吃(东西)
    方法,并将
    吃(生物)
    吃(食物)
    方法添加到
    老虎
  • 将逻辑移到
    对象
    。调用
    thing.beingEaten()
    ,并覆盖
    生物
    中的该方法,以调用
    doSomething
    而不是
    eat
  • 编辑:

    只有当对象是
    生物时,如何调用
    doOneThing()

    带有instanceof:

    class Tiger extends Pet {
        void eat (Thing thing) {
            if (thing is instanceOf Creature) {
                doOneThing();
            } else {
                doOtherThing();
            }
        }
    }
    
    class Tiger extends Pet {
        void eat(Thing thing) {
            thing.beEaten();
        }
    }
    
    class Creature extends Thing {
        void beEaten() {
            doOneThing();
        }
    }
    
    class Thing {
        void beEaten() {
            doOtherThing();
        }
    }
    
    没有instanceof:

    class Tiger extends Pet {
        void eat (Thing thing) {
            if (thing is instanceOf Creature) {
                doOneThing();
            } else {
                doOtherThing();
            }
        }
    }
    
    class Tiger extends Pet {
        void eat(Thing thing) {
            thing.beEaten();
        }
    }
    
    class Creature extends Thing {
        void beEaten() {
            doOneThing();
        }
    }
    
    class Thing {
        void beEaten() {
            doOtherThing();
        }
    }
    

    我可以想出几种解决办法:

  • 将检查移动到Thing:
    if(Thing.isEatable())
  • 如果不可吃,让thing抛出异常:
    尝试{eat(thing);}catch…
  • 不要以为所有的宠物都能吃东西。从宠物中移除
    吃(东西)
    方法,并将
    吃(生物)
    吃(食物)
    方法添加到
    老虎
  • 将逻辑移到
    对象
    。调用
    thing.beingEaten()
    ,并覆盖
    生物
    中的该方法,以调用
    doSomething
    而不是
    eat
  • 编辑:

    只有当对象是
    生物时,如何调用
    doOneThing()

    带有instanceof:

    class Tiger extends Pet {
        void eat (Thing thing) {
            if (thing is instanceOf Creature) {
                doOneThing();
            } else {
                doOtherThing();
            }
        }
    }
    
    class Tiger extends Pet {
        void eat(Thing thing) {
            thing.beEaten();
        }
    }
    
    class Creature extends Thing {
        void beEaten() {
            doOneThing();
        }
    }
    
    class Thing {
        void beEaten() {
            doOtherThing();
        }
    }
    
    没有instanceof:

    class Tiger extends Pet {
        void eat (Thing thing) {
            if (thing is instanceOf Creature) {
                doOneThing();
            } else {
                doOtherThing();
            }
        }
    }
    
    class Tiger extends Pet {
        void eat(Thing thing) {
            thing.beEaten();
        }
    }
    
    class Creature extends Thing {
        void beEaten() {
            doOneThing();
        }
    }
    
    class Thing {
        void beEaten() {
            doOtherThing();
        }
    }
    

    使用
    Map
    尝试此解决方案:

    import java.util.Map;
    import java.util.HashMap;
    
    interface ToDo {
      void exec();
    }
    
    abstract class Animal {}
    
    class Tiger extends Animal {}
    
    class Dog extends Animal {}
    
    class Ideone {
      public static void main(String[] args) {
        Map <Class, ToDo> map = new HashMap <Class, ToDo>();
        map.put(Tiger.class, new ToDo() {
            public void exec() {
                System.out.println("do for tiger ...");
            }
        });
        map.put(Dog.class, new ToDo() {
            public void exec() {
                System.out.println("do for dog ...");
            }
        });
        for(Animal a : new Animal[]{new Tiger(), new Dog(), null}) {
            try {
                map.get(a.getClass()).exec();
            } catch (NullPointerException npe) {
                System.out.println("nothing to do ...");
            }
        }
      }
    }
    
    import java.util.Map;
    导入java.util.HashMap;
    接口待办事项{
    void exec();
    }
    抽象类动物{}
    类{}
    类狗扩展动物{}
    表意文字{
    公共静态void main(字符串[]args){
    Map Map=newhashmap();
    map.put(Tiger.class,new ToDo()){
    public void exec(){
    System.out.println(“为老虎做…”);
    }
    });
    map.put(Dog.class,new ToDo()){
    public void exec(){
    System.out.println(“为狗做…”);
    }
    });
    对于(动物a:新动物[]{new Tiger(),new Dog(),null}){
    试一试{
    get(a.getClass()).exec();
    }捕获(NullPointerException npe){
    System.out.println(“无事可做…”);
    }
    }
    }
    }
    
    使用
    Map
    尝试此解决方案:

    import java.util.Map;
    import java.util.HashMap;
    
    interface ToDo {
      void exec();
    }
    
    abstract class Animal {}
    
    class Tiger extends Animal {}
    
    class Dog extends Animal {}
    
    class Ideone {
      public static void main(String[] args) {
        Map <Class, ToDo> map = new HashMap <Class, ToDo>();
        map.put(Tiger.class, new ToDo() {
            public void exec() {
                System.out.println("do for tiger ...");
            }
        });
        map.put(Dog.class, new ToDo() {
            public void exec() {
                System.out.println("do for dog ...");
            }
        });
        for(Animal a : new Animal[]{new Tiger(), new Dog(), null}) {
            try {
                map.get(a.getClass()).exec();
            } catch (NullPointerException npe) {
                System.out.println("nothing to do ...");
            }
        }
      }
    }
    
    import java.util.Map;
    导入java.util.HashMap;
    接口待办事项{
    void exec();
    }
    抽象类动物{}
    类{}
    类狗扩展动物{}
    表意文字{
    公共静态void main(字符串[]args){
    Map Map=newhashmap();
    map.put(Tiger.class,new ToDo()){
    public void exec(){
    System.out.println(“为老虎做…”);
    }
    });
    map.put(Dog.class,new ToDo()){
    public void exec(){
    System.out.println(“为狗做…”);
    }
    });
    对于(动物a:新动物[]{new Tiger(),new Dog(),null}){
    试一试{
    get(a.getClass()).exec();
    }捕获(NullPointerException npe){
    System.out.println(“无事可做…”);
    }
    }
    }
    }
    
    使用
    Map
    尝试此解决方案:

    import java.util.Map;
    import java.util.HashMap;
    
    interface ToDo {
      void exec();
    }
    
    abstract class Animal {}
    
    class Tiger extends Animal {}
    
    class Dog extends Animal {}
    
    class Ideone {
      public static void main(String[] args) {
        Map <Class, ToDo> map = new HashMap <Class, ToDo>();
        map.put(Tiger.class, new ToDo() {
            public void exec() {
                System.out.println("do for tiger ...");
            }
        });
        map.put(Dog.class, new ToDo() {
            public void exec() {
                System.out.println("do for dog ...");
            }
        });
        for(Animal a : new Animal[]{new Tiger(), new Dog(), null}) {
            try {
                map.get(a.getClass()).exec();
            } catch (NullPointerException npe) {
                System.out.println("nothing to do ...");
            }
        }
      }
    }
    
    import java.util.Map;
    导入java.util.HashMap;
    接口待办事项{
    void exec();
    }
    抽象类动物{}
    类{}
    类狗扩展动物{}
    表意文字{
    公共静态void main(字符串[]args){
    Map Map=newhashmap();
    map.put(Tiger.class,new ToDo()){
    public void exec(){
    System.out.println(“为老虎做…”);
    }
    });
    map.put(Dog.class,new ToDo()){
    public void exec(){
    System.out.println(“为狗做…”);
    }
    });
    对于(动物a:新动物[]{new Tiger(),new Dog(),null}){
    试一试{
    get(a.getClass()).exec();
    }捕获(NullPointerExcepti)