Я согласен, что не следует думать о введении ИЛИ, используя некоторые шаблоны проектирования. Шаблоны проектирования предназначены для решения очень специфических проблем в данном контексте.
Об интерфейсах и наследовании:
Интерфейсы используются, когда вам нужен полиморфизм времени выполнения. Итак, вы определяете интерфейс и можете иметь несколько различных его реализаций. В коде клиента вы можете просто объявить ссылку как тип интерфейса. Теперь вы не беспокоитесь о фактическом типе объекта, переданного клиенту во время выполнения. Вы просто заботитесь о вызове метода по ссылке.
interface Car {
void startEngine();
void stopEngine();
}
class Maruti implements Car {
public void startEngine() {
System.out.println("Maruti engine started");
}
@Override
public void stopEngine() {
System.out.println("Maruti engine stopped");
}
}
class Porsche implements Car {
@Override
public void startEngine() {
System.out.println("Porsche engine started");
}
@Override
public void stopEngine() {
System.out.println("Porsche engine stopped");
}
}
В приведенном выше примере в качестве клиента вы бы просто объявили ссылку как Тип автомобиля. И во время выполнения вы можете иметь объект Maruti или объект Porsche, вам все равно. То, что вас волнует, это просто позвонить startEngine или stopEngine.
Наследование обычно используется для повторного использования и расширения кода. Итак, у вас есть общий код в двух классах, и оба кажутся принадлежащими к общему типу, тогда вы можете создать родительский класс (иногда абстрактный) и переместить общий код в родительский класс. Таким образом, вы можете избавиться от дубликата кода. Другой вариант использования - это расширяемость, иногда у вас нет контроля над исходным кодом класса, и все же вы хотели бы добавить / изменить некоторое поведение. Вы можете использовать наследование и переопределить определенные методы.
Существует еще одна вещь, называемая "состав" , которая является предпочтительным способом наследования для расширяемости.