2016-10-18 9 views
3

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

можно либо определить сеттер явно с abstract класса, а затем продлить этот класс, или я могу реализовать interface. Но с interface мне пришлось бы писать метод setter снова и снова, что, по-видимому, нарушает принцип DRY.

public abstract class AbstractParent { 
    int value; 
    protected void setValue(int value) { 
     this.value = value; 
    } 
} 

против

public interface MyInterface { 
    void setValue(int value); 
} 

Когда имеет смысл использовать, какой подход?

+1

Если вам приходится писать одно и то же снова и снова, нет смысла делать его абстрактным. Определите его в суперклассе, и если он изменится в определенном подклассе, просто переопределите его. – Gendarme

+0

Разве это не значит, что я должен * сделать это абстрактным классом? Определите сеттер в абстрактном классе (используя 'protected'), а затем переопределите его, если я захочу? Я не говорю, чтобы сделать абстрактные методы setter абстрактным классом - это в основном то же самое, что использовать интерфейс, который является другой частью моего вопроса для начала. –

+0

Я добавил код, чтобы уточнить –

ответ

2

Наиболее абстрактно ("лучший") способ заключается в использовании как:

// The contract 
public interface MyInterface { 
    void setValue(int value); 
} 

// A convenient implementation from which to base a concrete implementation 
public abstract class AbstractParent implements MyInterface { 
    int value; 
    void setValue(int value) { 
     this.value = value; 
    } 
} 

Вы можете увидеть эту модель в действии на протяжении JDK, например:

interface Map {... 

abstract class AbstractMap implements Map {... 

class HashMap extends AbstractMap {... 

Этот шаблон позволяет кодировщикам предоставлять свои собственные классы, которые соответствуют контракту, что может быть особенно важно при модульном тестировании кода, который использует эти объекты, потому что гораздо проще обмануть интерфейс tha n класс, который может быть окончательным, имеет частные конструкторы или другие неудобные функции.

+0

Какова цель использования обоих? И разве это не требует от меня какого-то нарушения принципа DRY? Теперь, если я изменяю метод в интерфейсе, я должен изменить его в абстрактном классе и т. Д. Но в любом случае, почему и то и другое? –

+0

@ArukaJ Совсем нет. Где дублирование? См. [Принцип замены Лискова] (https://en.wikipedia.org/wiki/Liskov_substitution_principle). Изменение интерфейсов происходит нечасто, потому что это изменение * контракта * или * API *. Изменение * реализаций * однако * является * общим. – Bohemian

+0

Что касается Лискова: если T является родительским элементом S, то T можно заменить на S? Какие? Как это применимо здесь? –

0

В вашем случае Interface вместо abstract класс должен использоваться, если вы хотите иметь чистый контракт без реализации или ваши дочерние классы должны уже расширять другой класс, и вас раздражает, потому что класс не может расширять два класса.

Если это не так, абстрактного класса должно быть достаточно.
Не делайте сложной ситуации, когда вы можете сделать это легко.

0

Это правило большого пальца - это 1. Используйте абстрактный класс, если вы хотите переместить общую реализацию из клиентских (под) классов. Else не использует абстрактный, поскольку java предоставляет только один класс для расширения. 2. Используйте класс интерфейса, чтобы обеспечить соблюдение класса клиента для реализации поведения, чтобы ваш клиентский класс по-прежнему предоставлял возможность расширения других классов, если это необходимо.

public interface SetterInterface { 
    void setValue(int value); 
} 

// Here MyClass is can still extend any other class if needed, 
class MyClass implements SetterInterface { 
0

Лучше использовать композицию, чем наследование. Можете ли вы вывести это значение и настроить его в другой класс, а затем иметь экземпляр этого класса в качестве члена в других классах. Это намного чище, чем обманывание с иерархиями наследования

1

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

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

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

Если вы хотите обеспечить соблюдение шаблона, а не повторять себя, абстрактный класс - это путь сюда.

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

  • Нет связанных вопросов^_^