It has been repeatedly said that the instanceof operator should not be used except in the equals() method, otherwise it\'s a bad OOP design.
Some wrote that this is a
instanceof is a type system escape hatch. It can be used to do really evil things, like make generics not really generic, or extend a class hierarchy with ad-hoc virtual methods that never appear in the visible interface of those classes. Both of these things are bad for long-term maintainability.
More often than not, if you find yourself wanting to use instanceof, it means that there is something wrong with your design. Breaking the type system should always be a last resort, not something to be taken lightly.
I do not think your particular example warrants using instanceof. The object-oriented way to do this is to use the visitor pattern:
abstract class Animal {
def accept(v: AnimalVisitor)
}
trait Edible extends Animal {
def taste : String
def accept(v: AnimalVisitor) = v.visit(this)
}
trait Pet extends Animal {
def growl : String
def accept(v: AnimalVisitor) = v.visit(this)
}
abstract class AnimalVisitor {
def visit(e: Edible)
def visit(p: Pet)
}
class EatOrPlayVisitor {
def visit(e: Edible) = println("it tastes " + e.taste)
def visit(p: Pet) = println("it says: " + p.growl)
}
class Chicken extends Animal with Edible {
def taste = "plain"
}
class Lobster extends Animal with Edible {
def taste = "exotic"
}
class Cat extends Animal with Pet {
def growl = "meow"
}
class Dog extends Animal with Pet {
def growl = "woof"
}
object Main extends App {
val v = new EatOrPlayVisitor()
val as = List(new Chicken(), new Lobster(), new Cat(), new Dog())
for (a <- as) a.accept(v)
}
NOTE: I am aware that Scala has case classes, but I wanted to provide a general object-oriented solution.