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.
Related
To access sub-class method down-casting is needed, is there is a way to achieve this using generic without type-casting in same manner.
public class Main {
public static void main(String[] args){
Animal parrot = new Bird();
((Bird)parrot).fly();
}
}
interface Animal{
void eat();
}
class Bird implements Animal{
#Override
public void eat() {}
public void fly(){}
}
public class Main {
public static void main(String[] args){
Animal parrot = new Bird();
parrot.move();
}
}
interface Animal{
void eat();
void move();
}
class Bird implements Animal{
#Override
public void eat() {}
public void move(){fly();}
public void fly(){}
}
It could work with something like this I guess
Interfaces are meant to add methods to implemented classes without defining actual code for this method, meaning that any implemented class will definitely have the same methods but 2 implemented methods with the same name won't necessarily perform the same action.
To explain it with the current thread it would be:
interface Animal {
void move();
}
class Bird implements Animal{
public void move(){
fly();
}
}
class Dog implements Animal{
public void move(){
walk();
}
}
This way, each class will have its own definition of the move method while in main each method will be called by object.move().
This way of doing things allows to go from a code like this
for (object tmp:objList){
if(tmp.class=="Bird")
tmp.fly();
}
else if (tmp.class=="Dog"){
tmp.walk();
}
...
}
to
for (object tmp:objList){
tmp.move();
}
The parrot class should extend the Bird class, then you can call the fly method from a parrot object directly and without need to cast.
public class Parrot extends Bird{
//have some filed or method
}
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();
}
}
}
Let's say I have following interface:
interface Mammal {
void marry(Mammal m);
Mammal giveBirthTo();
}
However, this doesn't say quite exactly what I want.
Obviously, a human can't marry a dog, nor give birth to a cat. So how can I embed this information into the interface, such that the input type and output type can be changed automatically as it gets implemented?
You could use generics and change your design.
Something in the lines of:
interface Marriable<T extends Mammal> {
void marry(T sweetHalf);
T giveBirthTo();
}
... where Mammal is your top interface or abstract class, and Human, Dog, Unicorn etc. extend / implement it.
You can generify your interface using a recursive type variable:
interface Mammal<T extends Mammal<T>> {
void marry(T m);
T giveBirthTo();
}
This way, the Java compiler can give you a certain validation level. Notice however that this approach is still open to abuse. For example:
class Cat implements Mammal<Cat> {
#Override void marry(Cat cat) { ... }
#Override Cat giveBirthTo() { ... }
}
class Dog implements Mammal<Cat> { // implements wrong interface
#Override void marry(Cat cat) { ... }
#Override Cat giveBirthTo() { ... }
}
The compiler can only assure that you implement the Mammal interface by some sub type of the same interface, but not by the particular class that implements it. This latter type constraint cannot be expressed in the Java programming language.
Generics. Try with
private static interface Race {
}
private static class Human implements Race {}
private static class Canine implements Race {}
private static interface Being<R extends Race> {
void marry(Being<R> other);
Being<R> giveBirthTo();
}
private void tryMe() {
Being<Human> aHuman = new Being<Human>() {
#Override
public void marry(Being<Human> other) {
}
#Override
public Being<Human> giveBirthTo() {
return null;
}
};
Being<Canine> aCanine = new Being<Canine>() {
#Override
public void marry(Being<Canine> other) {
}
#Override
public Being<Canine> giveBirthTo() {
return null;
}
};
aHuman.marry(aCanine); // not possible
}
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.
Sometimes, I came across some class design as follow.
abstract class animal {
public abstract void speak();
}
class dog extends animal {
#Override
public void speak() {
// Do something.
}
}
abstract class abstract_dog extends dog {
#Override
public abstract void speak();
}
I was wondering, what is the purpose of having an abstract_dog class? Why we "transform" the non-abstract speak method into abstract speak again?
In case you want to create a base class that forces people to override speak, but inherits Dog.
I agree with SLaks, and think that this would be a real life situation:
abstract class animal {
public abstract void speak();
}
class dog extends animal {
#Override
public void speak() {
// Dog says 'bark'
}
}
abstract class abstract_dog extends dog {
#Override
public abstract void speak();
}
class poodle extends abstract_dog {
#Override
public void speak() {
// poodle says 'yip yip'
}
}
class great_dane extends abstract_dog {
#Override
public void speak() {
// great dane says 'ruff ruff'
}
}
I think you would use this in the case where you want the make a new child class implement the speak method and the dog class may have other methods that the new child class would not have to implement.
Knowing more about your exact situation would help in determining if there is a better design for this scenario.