Во время рефакторинга мне нужно было расширить существующий интерфейс, добавив дополнительный параметр. В настоящее время существует много старых классов, которые реализуют версию без параметров, а также некоторые новые классы, которые реализуют версию с параметром:методы экземпляра против перенаправления
void exec(int parameter);
против
void exec();
В конце концов, мне нужно, чтобы принять классы, реализующие оба интерфейса в та же коллекция и последующий процесс внутри того же метода. Кажется, существуют два возможных подхода к этому:
\ 1. Используйте instanceof
:
int parameter = ...
if (a instanceof NewInterface)
((NewInterface) a).exec(parameter);
else
((OldInterface) a).exec();
Преимущества этого является то, что NewInterface
и OldInterface
могут быть независимыми интерфейсами. Когда разработчик пишет новый класс, может быть более очевидным, какие методы переопределить, а переопределение неправильного метода приведет к ошибке времени компиляции.
\ 2. Используйте единый интерфейс с обеими методами, определенных и родительским абстрактным классом, который перенаправляет от одного метода к другому:
abstract class Common {
abstract void exec();
void exec(int param) { exec(); }
}
Это позволяет избежать instanceof
, что считается плохим в некоторых дискуссиях, но теперь в каждом новом классе мы должны добавить странный окурок:
// This is not used anymore
void exec() { };
// This is a real functionality
void exec(int param) { ...
не похоже, лучший дизайн когда-либо либо, особенно принимая во внимание возможность вызывать эту заглушку по ошибке.
Должен ли я использовать какой-либо третий подход, или это тот случай, когда использование экземпляра является разумным?
У вас есть доступ ко всей базе данных, использующей ваш метод? – user3707125
Да, но я бы предпочел избежать массового добавления неиспользуемого параметра в объявление многих методов, которые ему не нужны. Если это действительно единственный правильный путь, это будет возможным ответом. – h22
@ h22, но это правильная вещь. Контракт интерфейса говорит о том, что exec() принимает параметр, и это зависит от реализации, чтобы что-то сделать с ним или игнорировать его. –