Avoiding use of 'instanceof' - java

I'm struggling with how I might avoid using instanceof() in some of my code. This contrived example somewhat captures the problem.
Class Meat extends Food;
Class Plant extends Food;
Class Animal;
Class Herbivore extends Animal
{
void eat( Plant food);
}
Class Carnivore extends Animal
{
void eat( Meat food);
}
Class Omnivore extends Animal
{
void eat(Food food);
}
Class Zoo
{
List<Animals> animals;
void receiveFood( Food food)
{
// only feed Plants to Herbivores and Meat to Carnivores
// feed either to Omnivores
}
}
Herbivores are only interested in Plants, Carnivores only in Meat and Omnivores both. When the Zoo receives Food it only makes sense to try to feed food to animals that eat that type of food.
I've thought of a few solutions, but all seem to depend on the use of instanceof() somewhere and my various refactorings just seem to move it around.
(1) I could implement eat( Food food) in Animal and each subclass could choose to ignore food that it doesn't eat, but that is inefficient and would require that each Animal subclass use instanceof() to test the type of food.
(2) I could keep three collections of animals in the Zoo based on the type of food they eat, but would still have to use instanceOf() to test the type of food to see which collection to feed it to. At least this would be more efficient as I wouldn't be feeding food to Animals that won't eat it.
I've thought of some other approaches, but again, they just seem to pass the instanceof() buck.
Any suggestions? Or would this (2, at least) be an acceptable use of instanceof()?

The visitor pattern solves your problem. Here's the code:
public abstract class Animal {
public abstract void accept(AnimalVisitor visitor);
}
public interface AnimalVisitor {
public void visit(Omnivore omnivore);
public void visit(Herbivore herbivore);
public void visit(Carnivore carnivore);
}
public class Carnivore extends Animal {
#Override
public void accept(AnimalVisitor visitor) {
visitor.visit(this);
}
public void eat(Meat meat) {
System.out.println("Carnivore eating Meat...");
}
}
public class Herbivore extends Animal {
#Override
public void accept(AnimalVisitor visitor) {
visitor.visit(this);
}
public void eat(Plant plant) {
System.out.println("Herbivore eating Plant...");
}
}
public class Omnivore extends Animal {
#Override
public void accept(AnimalVisitor visitor) {
visitor.visit(this);
}
public void eat(Food food) {
System.out.println("Omnivore eating " + food.getClass().getSimpleName() + "...");
}
}
public abstract class Food implements AnimalVisitor {
public void visit(Omnivore omnivore) {
omnivore.eat(this);
}
}
public class Meat extends Food {
#Override
public void visit(Carnivore carnivore) {
carnivore.eat(this);
}
#Override
public void visit(Herbivore herbivore) {
// do nothing
}
}
public class Plant extends Food {
#Override
public void visit(Carnivore carnivore) {
// do nothing
}
#Override
public void visit(Herbivore herbivore) {
herbivore.eat(this);
}
}
public class Zoo {
private List<Animal> animals = new ArrayList<Animal>();
public void addAnimal(Animal animal) {
animals.add(animal);
}
public void receiveFood(Food food) {
for (Animal animal : animals) {
animal.accept(food);
}
}
public static void main(String[] args) {
Zoo zoo = new Zoo();
zoo.addAnimal(new Herbivore());
zoo.addAnimal(new Carnivore());
zoo.addAnimal(new Omnivore());
zoo.receiveFood(new Plant());
zoo.receiveFood(new Meat());
}
}
Running the Zoo demo prints
Herbivore eating Plant...
Omnivore eating Plant...
Carnivore eating Meat...
Omnivore eating Meat...

In your case, if the consumer of the object must know certain things about that object (e.g. is it meat), include a property in your base class isMeat() and have concrete subclasses override the implementation of the base class method to return an appropriate value.
Leave that knowledge in the class itself, rather than in consumers of the class.

A simple solution is when using multiple custom classes interacting with one another, just create isFood(), isAnimal(), isCarnivore(), etc. methods that return a boolean depending on which class they're in. It's not the prettiest but it gets the job done 100% of the time.

Expanding on my comment, I would attempt to use generics to help me here:
interface Animal<T extends Food> {
void eat(T food);
}
class Herbivore extends Animal<Plant> {
void eat(Plant food) { foo(); }
}
class Carnivore extends Animal<Meat> {
void eat(Meat food) { bar(); }
}
Note that this still doesn't solve the problem of iterating through a list of Food and Animal and only sending appropriate food to each animal -- I don't see a way to do that without explicit instanceof style checks. But, it does allow you to be more specific with what your subclasses accept.

Another solution is to maintain 2 lists: one for Herbivores and one for Carnivores.

Related

How can I structure my classes which usually need to be called together?

I have some related classes that implement the same method
class Dog {
public void speak() { System.out.println("Bark") }
}
class Cat {
public void speak() { System.out.println("Meow") }
}
90% of the time, users would want both the dog and the cat to speak. They don't want to know the details. When we add a new animal, they'll want it to speak too. The idea is to avoid:
// All animals need to be explicitly told to speak every time
new Dog().speak();
new Cat().speak();
// But we just added Birds, and the users need to remember to add this call everywhere
new Bird.speak();
I could do something like
class Animals {
public void speak() {
new Dog().speak();
new Cat().speak();
new Bird().speak();
}
}
So that users can just call new Animals().speak() every time.
However, 10% of the time, it does need to be configurable. What I want is a way for users to do something like this
// Used most of the time
Animals.withAllAnimals().speak();
// Sometimes they don't want cats, and they want the dogs to woof instead
Animals.exclude(Cat)
.configure(Dog.sound, "Woof")
.speak();
How can I structure my classes to accomplish this?
I know that it is question tagged with java. However, let me show an example with C# as these languages have many common things.
The first thing is I would use inheritance and create abstract class Animal as common behaviour Speak() is used. So, abstract class should define behavior, and the derived classes should implement that behavior:
public abstract class Animal
{
public abstract void Speak();
}
Then just use inheritance and override behaviour in derived classes:
public class Bird : Animal
{
public override void Speak()
{
System.Console.WriteLine("I am a bird!");
}
}
public class Cat : Animal
{
public override void Speak()
{
System.Console.WriteLine("I am a cat!");
}
}
public class Dog : Animal
{
public override void Speak()
{
System.Console.WriteLine("I am a dog!");
}
}
Then we need a class that allows to speak for all animals. Let's create Choir class for this purpose:
public class Choir
{
private List<Animal> choristers;
public void AddChoristers(IEnumerable<Animal> choristers)
{
if (choristers == null)
choristers = new List<Animal>();
choristers.AddRange(choristers);
}
public void SpeakAll()
{
foreach (Animal animal in choristers)
animal.Speak();
}
public void Speak(Func<Animal, bool> filter)
{
IEnumerable<Animal> filteredAnimals = choristers
.Where(filter ?? (animal => true));
foreach (Animal animal in filteredAnimals)
animal.Speak();
}
}
Pay attention to Speak() method. It can take a predicate as a parameter, so you can choose desired animals to speak().
Here are some ideas.
import java.util.*;
import java.util.function.Consumer;
/**
* An animal can either speak with its own voice, or another supplied
*/
interface Animal {
String speak();
String speak(String voice);
}
/**
* Base class for animal implementations.
*
* An animal is added to a Menagerie when created.
*/
abstract class BaseAnimal implements Animal {
private final String defaultVoice;
public BaseAnimal(Menagerie menagerie, String defaultVoice) {
this.defaultVoice = defaultVoice;
menagerie.add(this);
}
public String speak(String voice) {
return voice;
}
public String speak() {
return speak(defaultVoice);
}
}
/**
* A Dog. Even when given a voice the dog does things slightly differently.
*/
class Dog extends BaseAnimal {
public Dog(Menagerie menagerie) {
super(menagerie, "Bark!");
}
public String speak(String voice) {
return voice + " (and drools)";
}
}
/**
* A collection of animals. We can do something side-effectful to each, or create a new collection where
* some classes of animal are excluded or have different behaviour.
*/
interface Animals {
void forEach(Consumer<Animal> action);
Animals exclude(Class<Animal> clazz);
Animals configureVoice(Class<Animal> clazz, String voice);
}
/**
* An Animals instance which can contain only a single animal of each class
* (an arbitrary decision based on the code in the question)
*/
class Menagerie implements Animals {
Map<Class<? extends Animal>,Animal> animals = new HashMap<>();
public Menagerie() {
}
public Menagerie(Map<Class<? extends Animal>, Animal> animals) {
this.animals = new HashMap<>(animals);
}
public void add(Animal animal) {
animals.put(animal.getClass(), animal);
}
public void forEach(Consumer<Animal> action) {
animals.values().forEach(action);
}
#Override
public Animals exclude(Class<Animal> clazz) {
Menagerie m = new Menagerie(animals);
m.animals.remove(clazz);
return m;
}
/**
* Return an Animals instance which contains a proxy for a particular type of animal
* which will behave differently when speak() is called.
*/
#Override
public Animals configureVoice(Class<Animal> clazz, String voice) {
Menagerie m = new Menagerie(animals);
Animal a = m.animals.get(clazz);
if (a != null) {
m.animals.put(clazz, new Animal() {
#Override
public String speak() {
return voice;
}
#Override
public String speak(String voice) {
return a.speak(voice);
}
});
}
return m;
}
}

List<Super Class> which contains objects of different subclasses

Now I have a class Animal, with three subclasses extending it: Dog, Cat, and Fish.
class Dog extends Animal {
public void bark(){}
}
class Cat extends Animal {
public void catchMouse(){}
}
class Fish extends Animal {
public void swim(){}
}
And I have a list:
List<Animal> listOfAnimals = new ArrayList<>();
Then I use a static method to add objects of Dog, Cat and Fish to the list:
public static void addAnimal(List<Animal> list, AnimalInfo info) {
Animal animal = new Animal();
switch (info) {
case 0:
animal = new Dog();
break;
case 1:
animal = new Cat();
break;
case 2:
animal = new Fish();
break;
}
list.add(animal);
}
I call this static method 3 times and add a Dog object, a Cat object and a Fish object to the list in order. Now the list should contain a Dog instance, a Cat instance and a Fish instance.
Now I want to call bark() on the Dog instance:
list.get(0).bark();
But this will not work obviously.
What is the best way to achieve this? Use:
(Dog)(list.get(0)).bark();
?
I think utilizing inheritance here could be a good approach in this case, but I thought I'd share an alternative.
Another approach here is to use the visitor pattern. This is especially good when you don't know what you need to do with an object when you declare its class, or if you have contextual behaviour (such as updating another object's state) that you want to keep separate from your Animal classes (Separation of Concerns)
abstract class Animal {
abstract void accept(AnimalVisitor visitor);
}
class Dog extends Animal {
void bark() { ... }
#Override
void accept(AnimalVisitor visitor) {
visitor.visit(this);
}
}
class Cat extends Animal {
void meow() { ... }
#Override
void accept(AnimalVisitor visitor) {
visitor.visit(this);
}
}
interface AnimalVisitor {
void visit(Dog dog);
void visit(Cat cat);
}
// Somewhere else...
AnimalVisitor voiceVisitor = new AnimalVisitor() {
#Override
void visit(Dog dog) {
dog.bark();
}
#Override
void visit(Cat cat) {
cat.meow();
}
}
animalList.get(0).accept(voiceVisitor);
What is the best way to achieve this?
If you use List of Animals you should use Animal-only methods further in program logick.
The idea of List is that you iterating over it any apply the same to items.
Make:
class Animal {
public void voice(){}
public void swim(){}
}
class Dog extends Animal {
public void voice(){
print('bark')}
}
class Cat extends Animal {
public void voice(){
print('meow')}
}
And if you do want to have a list of all animals, they just do noting, instead of calling is instance of what is more expencive
Another way of doing this is through interface
interface IAnimal {
public void Roar();
public void Swim();
}
class Animal implements IAnimal{
#Override
public void Roar() {
// TODO Auto-generated method stub
System.out.println("IROAR");
}
#Override
public void Swim() {
// TODO Auto-generated method stub
if (!(this instanceof Lion)) {
System.out.println("ISWIM");
}
else {
System.out.println("this animal cannot swim");
}
}
}
Notice that I added a check for Lion instance for Swim() method since not all animals can swim.
Client Code:
List<IAnimal> animals = new ArrayList<>();
animals.add(new Lion());
animals.add(new Dog());
animals.get(0).Swim();
animals.get(1).Roar();

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
Is there some way to do validations on subclasses, such as cat and eagle without instanceof check ?
Any good design pattern ( assuming subclasses dont share a method in base class ? )
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() { ... }
}
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());
(1) Is there some way to do validations on subclasses, such as cat and eagle without instanceof check ?
yes, there is. You could define a "validate" method (abstract in "Animal" class) and implement it in the specific subclasses. Depending on the validation result (e.g. exception / problem list) you can have the validate method throw some kind of "InvalidContentException" or provide the method call with an "ErrorHandler" that is informed about the bad things of an instance.
(2) assuming that the subclasses don't share a method in the base class: well, that one is a bit counter intuitive. On one hand you want to be able to do something on an "Animal", yet you don't want to define that capability on it?
You could define a Validator class that has separate validation methods (on for each kind of "Animal" subclass). That would eliminate the instanceof checks, however you would never be able to pass this Validator class other "Animals" (such as "Dog"), only "Cat" and "Eagle" (or subclasses thereof). You might also want to consider what you want to happen when passing subclasses of "Cat": are all sublasses of Cat validated in the same way or is there subclass specific behavior (like color, size, ...) for the different cat classes?
--> I think you should ask yourself if you want to be able to validate animals in general. Without having insight into your problem domain (which might have reasons not to do it), I'd recommend to have a "validate" method on the animal. You could also go for a visitor pattern, but that requires the Animal to have a "accept(AnimalVisitor visitor)" method and is slightly more code to write (presumably more than you want to)
This is when polymorphism comes in handy.
abstract class Animal {
abstract public void process(Animal animal);
}
class Cat extends Animal {
#Override
public void process(Animal animal) {
if (!this.meow()) {
throw exception("cat does not meow");
} else {
this.feedFish();
}
}
}
class Eagle extends Animal {
#Override
public void process(Animal animal) {
if (!this.fly()) {
throw exception("eagle does not fly");
} else {
this.checkMaxFlightAltitude();
}
}
}

Incorporating Polymorphism

I'm new to Java and need to employ polymorphism into the following lines:
horse.feed();
horse.wash();
horse.exercise();
How do I do this?
These are the first lines of the code in this exercise:
public class Main extends Object {
public static void main(String [] args) {
Horse horse = new horse();
}
}
Answering the question from your comment: "Could someone write out how it should look so I can better understand it."
Let's create an interface Animal
public interface Animal {
public void feed();
public void wash();
public void exercise();
}
And a class Horse:
public class Horse implements Animal {
#Override
public void feed() {
// Do something to feed the horse
}
#Override
public void wash() {
// Do something to wash the horse
}
#Override
public void exercise() {
// Do something to exercise the horse
}
}
Now in your main method, you can create a horse that is an Animal and call the methods:
Animal horse = new Horse();
horse.wash();
// Etcetera
Now if you would make a class Dog, which also implements Animal, you could make a List of Animals and add Horses and Dogs to one List!

Avoid using instanceOf in observer method

I have the following system in Java:
public class Human {
public void drown(Animal animal) {
if (animal instanceOf Fish) {
return;
} else {
animal.die();
}
}
}
public abstract class LandAnimal extends Animal{...}
public class Tiger extends LandAnimal{...}
public abstract class Fish extends Animal {...}
public class Trout extends Fish {...}
I have thought of adding a method
public abstract boolean drownable() {...}
in class Animal but I don't have access to the code of Animal class.
As I know the use of instanceOf is considered bad OOP practice. How do I avoid the use of instanceOf in this case? Thanks.
The drown() method in Human should be (by the way, why do humans want to drown animals?):
public void drown(Animal animal) {
animal.drown();
}
And each Animal will know what to do, for example:
// in class Tiger
public void drown() {
die();
}
// in class Fish
public void drown() {
// do nothing, fish can't drown
}
You would declare Animal.drown() and override it in Fish, containing the appropriate 'kill code' :).
So you'd just need to call drown() on each animal and each instance will behave according to its type specific method implementation.
public class Human {
public void drown(Animal animal) {
animal.drown();
}
}
Methods can be overloaded based on their arguments. You can have two different methods:
public void drown(Fish f) {
return;
}
public void drown(LandAnimal a) {
a.drown();
}
However, it should be noted that this makes determining whether some animal will drown the responsibility of the Human class, which, as other answers show, is arguable.

Categories