Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get rid of instanceof check when using inheritance?

Assume we have a class Animal, with subclasses as cat, eagle

Now I have a method:

public void process(Animal animal) {

   if (animal instanceof Cat) {
     if (!animal.meow()) {
        throw exception("cat does not meow");
     } else {
      animal.feedFish();
     }
   }

   if (animal instanceof eagle) {
      if (!animal.fly()) {
         throw exception("eagle does not fly");
      } else {
        animal.checkMaxFlightAltitude();
      }
   }
}

Here cat has 2 methods meow and feedfish which are completely different than eagle's methods fly and checkmaxflight

Most design patterns revolve around assumptions that subclasses have a common method like Shape draw() inherited by circle draw and square draw

  1. Is there some way to do validations on subclasses, such as cat and eagle without instanceof check ?

  2. Any good design pattern ( assuming subclasses dont share a method in base class ? )

like image 373
JavaDeveloper Avatar asked Dec 24 '22 22:12

JavaDeveloper


2 Answers

You could have an abstract process method in Animal and implement it in the subclasses:

class Animal {
  protected abstract void process();
  public static void process(Animal a) { a.process(); }
}

class Cat {
  void process() {
    if (!meow()) throw exception("cat does not meow");
    else feedFish();
  }
  public boolean meow() { ... }
  public void feedFish() { ... }
}
like image 154
assylias Avatar answered Dec 26 '22 12:12

assylias


You could use double dispatch by employing a visitor.

Example:

public class Animal {
    public abstract void accept(AnimalVisitor v);

    public boolean meow() {return false;}
    public boolean fly() {return false;}
    public void feedFish() {};
    public void checkMaxFlightAltitude() {};

}

public class Cat extends Animal {
    public void accept(AnimalVisitor v) {
        v.visitCat(this);
    }

    public boolean meow() {return true;}
}

public class Eagle extends Animal {
    public void accept(AnimalVisitor v) {
        v.visitEagle(this);
    }
    public boolean fly() {return true;}
}

public interface AnimalVisitor {
    void visitEagle(Eagle eagle);
    void visitCat(Cat cat);
}

public class AnimalVisitorExample implements AnimalVisitor {
    public void visitEagle(Eagle eagle) {
        eagle.checkMaxFlightAltitude();
    }

    public void visitCat(Cat cat) {
        cat.feedFish();
    }
}

Animal animal = new Cat();
animal.accept(new AnimalVisitorExample());
like image 45
massfords Avatar answered Dec 26 '22 12:12

massfords