Я использую Java 8 / Java 11. У меня есть иерархия типов (в основном dtos или Java Beans), например
public abstract class Animal {
public abstract String getName();
public abstract int getAge();
}
И некоторые реализации, предоставляющие дополнительные свойства:
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()"
}
Теперь я хотел бы обработать Collection
из Animal
с единообразным способом, например
animals.forEach(x -> {
System.out.println(x.getName()); // works
System.out.println(x.getSound(); // doesn't work, as Fish is missing the method
});
Мне было интересно, что было бы хорошим способом реализовать «отсутствующие» методы, предполагая, что они должны возвращать значение по умолчанию, например «n / a», для String
.
Один очевидный способ - переместить все отсутствующие методы в базовый класс и объявить они абстрагируют или обеспечивают реализацию по умолчанию. Но я бы хотел, чтобы они были более отдельными, то есть чтобы было понятно, какие свойства были добавлены для «равномерной обработки». Другой способ - ввести вспомогательный класс, используя instance of
, чтобы определить, отсутствует ли метод:
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";
}
}
, который затем вызывается с Animal
:
System.out.println(AnimalHelper.getSoundOrDefault(animal));
Это работает, но теперь вызывающая сторона должна определить, какие методы вызывать на Animal
напрямую и для каких методов использовать помощника.
Другое решение: я предложил добавить интерфейс AnimalAdapter
с использованием Java 8 особенность реализации по умолчанию:
public interface AnimalAdapter {
default String getSoundOrDefault() {
return "n/a";
}
}
И добавление ее в класс Animal
:
public abstract class Animal implements AnimalAdapter {
...
, что приводит к добавлению метода getSoundOrDefault()
в Dog
и Cat
, но не Fish
:
public class Dog extends Animal {
...
@Override
public String getSoundOrDefault() {
return getSound();
}
}
(аналогично Cat
).
Любые комментарии по вышеуказанным соображениям или другие идеи будут высоко оценены.