2015-05-29 3 views
3

В производственном коде я часто видеть классы, определенные следующим образом:Почему разделение интерфейса и реализация?

public interface SomeComponent { // Some methods } 
public class SomeComponentImpl implements SomeComponent { // Some methods} 

public interface SomeComponentV2 extends SomeComponent { // Some methods } 
public class SomeComponentV2Impl extends SomeComponentImpl implements SomeComponent { // Some methods } 

Почему в этом случае мы хотим, чтобы отделить интерфейс и его реализацию?

Или это следующим образом, почему это плохо, чтобы просто иметь один базовый класс, и пусть V2 продлить/переопределения V1 следующим образом:

public class SomeComponent { // Some methods } 
public class SomeComponentV2 extends SomeComponent 
{ 
    // Override methods for reimplementation 
    // Add new methods for new features. 
} 
+0

Вы, кажется, не используете интерфейс 'SomeComponentV2' в любом месте. Это намеренно? Кроме того, интерфейсы и классы пустые? Последнее, но не менее важное: спрашиваете, зачем использовать интерфейсы, когда вы можете просто использовать классы? – CKing

+0

Иногда существуют так называемые «маркерные» интерфейсы, которые не имеют тела, а просто идентифицируют объект как принадлежащий к определенной категории. Пример Serializable. – swingMan

+0

См. Мое обновление. Все классы/интерфейсы имеют контент. Они не являются пустыми маркерами, но в них есть реальный код. Я видел такой дизайн во многих исходных кодах производственных систем, поэтому интересно, почему. – OneZero

ответ

0

Разделительная интерфейс от реализации позволяет полностью использовать полиморфизм. Таким образом, SomeComponentV2Impl будет иметь 3 типа - собственный, базовый класс и интерфейс. Здесь вы можете использовать только интерфейс, не заботясь о его реализации в других классах. Например:

public void methodInOuterClass(SomeComponent smCmp){ 
    smCmp.runInterfaceMethods(); 
} 

[Edit: этот вопрос появился в OP вопрос перед edites]

Почему мы не используем один базовый класс для всех?

Потому что SomeComponentV2Impl отличается от SomeComponentImpl. Но если они реализуют один и тот же интерфейс, вы сможете назвать их реализацию из-за неоднозначности интерфейса.

+0

@downvoter, что случилось с моим ответом? – itwasntme

+0

это может показаться неправильным раньше, но только из-за интерфейсов и имен классов, сделанных OP, которые меня путают. Я считаю, что хорошая практика - назвать интерфейс SomethingModel или SmthInteface, а затем назвать первый класс, реализующий его как Something – itwasntme

1

Это хорошая практика для разделения интерфейса и реализации класса, поскольку вы можете легко менять классы.

Представьте, что вы хотите протестировать приложение, которое зависит от веб-службы, которая выставляет вам счета за каждый запрос. Помимо класса, который выполняет реальные запросы к этому веб-сервису, вы можете создать класс, который реализует один и тот же интерфейс, но возвращает поддельные данные, чтобы избежать генерации затрат для каждого запроса.

Каждый раз, когда вы наследуете базовый класс, есть вероятность, что вы наследуете поведение, которое вы просто не хотите наследовать. Интерфейс представляет собой чистый контракт и дает вам свободу выбора базового класса независимо от описанного преимущества.

+0

. Вы также можете расширить класс из фактического класса.Возможность иметь двойные тесты не обязательно является интерфейсом. Кроме того, Java 8 позволяет интерфейсам иметь методы по умолчанию, которые имеют тело, не являются абстрактными и наследуются их реализующими классами. Интерфейсы уже не просто чистые контракты. – CKing

Смежные вопросы