I'm using Java 8 / Java 11. I have a type hierarchy (basically dtos or Java Beans) like
public abstract class Animal {
public abstract String getName();
public abstract int getAge();
}
And some imeplementations providing additional properties:
public class Dog extends Animal {
// implementation of abstract methods from base class animal
// additional properties
public String getSound() {
return "woof";
}
}
public class Dog extends Animal {
// implementation of abstract methods from base class animal
// additional properties
public String getSound() {
return "miaow";
}
}
public class Fish extends Animal {
// implementation of abstract methods from base class animal
// no implementaion for "getSound()"
}
Now, I'd like to process a Collection
of Animal
s in a uniform way, e.g.
animals.forEach(x -> {
System.out.println(x.getName()); // works
System.out.println(x.getSound(); // doesn't work, as Fish is missing the method
});
I was wondering, what would be a good way to implement the "missing" methods assuming that they should return a default value like "n/a" for a String
.
One obvious way would be to move all the missing methods to the base class and either declare them abstract or provide a default implementation. But I'd like to have them more separate, i.e. making clear which properties were added for the "uniform processing". Another way would be to introduce a helper class using instance of
to determine, if the method is missing:
public class AnimalHelper {
public static String getSoundOrDefault(Animal animal) {
if (animal instanceof Dog) {
return ((Dog)animal).getSound();
}
if (animal instanceof Cat) {
return ((Cat)animal).getSound();
}
return "n/a";
}
}
which then gets called with an Animal
:
System.out.println(AnimalHelper.getSoundOrDefault(animal));
This works, but the caller must now which methods to call on Animal
directly and for which methods to use the helper.
Another solution, I came up with the adding an interface AnimalAdapter
using the Java 8 feature of default implementation:
public interface AnimalAdapter {
default String getSoundOrDefault() {
return "n/a";
}
}
And adding it to the Animal
class:
public abstract class Animal implements AnimalAdapter {
...
which results in adding the getSoundOrDefault()
method in Dog
and Cat
, but not Fish
:
public class Dog extends Animal {
...
@Override
public String getSoundOrDefault() {
return getSound();
}
}
(likewise in Cat
).
Any comments on the above considerations or other ideas would be highly appreciated.
Aucun commentaire:
Enregistrer un commentaire