Добавляйте методы в классы, не нарушая реализации

Скажем, у меня есть 2 класса с именем class Cow ad class Pig.

Оба они реализуют interface Animal.

Для interface есть только 2 метода с именами public void eat() и public void speak().

Все в порядке. Но хотя это кажется хорошим использованием interfaces, я подумал, что если мне когда-нибудь понадобится добавить метод(ы) к этому interface, реализация сломается, а именно мне нужно будет реализовать новые методы в этих классах, что нарушает "закрыть -открытый принцип».

Поэтому я подумал, что в дополнение к interface я бы также использовал класс abstract, если мне понадобится добавить новые методы в будущем.

Так, например, public class Cow extends ... implements Animal.

Звучит как хороший план (если это не так, пожалуйста, поправьте меня).

Но проблема в том, что если эти классы extend уже являются каким-то другим классом? В таком случае я не мог расширить 2 класса.

Итак, мой вопрос:

Есть ли шаблон, в котором я мог бы объявить общие interface связанных классов, удерживая при этом возможность добавлять новые методы в будущем, которые не нарушают «принцип закрытого-открытого» и не нарушают реализации?


person Unheilig    schedule 15.06.2014    source источник
comment
Это проблема, связанная с методами по умолчанию в Java 8. попытка обращения.   -  person Oliver Charlesworth    schedule 15.06.2014


Ответы (2)


В Java 8 есть методы по умолчанию

public interface Animal {

    void eat();
    void speak();
    default void sleep(){}

}

Теперь ваш Animal должен переопределить eat и speak, но вы можете переопределить sleep.

До Java 8 использование abstract class было обычным способом защиты от необходимости реализовывать каждый метод interface. Как вы заметили, это не работает с множественным наследованием, поэтому его нельзя использовать для решения всех случаев.

P.S. не объявляйте interface методы public, это видимость по умолчанию для всех interface участников.

person Boris the Spider    schedule 15.06.2014
comment
Спасибо за ответ. Итак, когда разработчику API нужно было добавить новый метод в следующую версию, как он это сделал (если класс уже расширил другой класс)? Не могли бы вы привести мне образец для этого (до Java 8)? Спасибо. - person Unheilig; 15.06.2014
comment
Пример @Unheilig см. в классе Number, где intValue и longValue объявлены как абстрактные методы, а byteValue и shortValue, добавленные начиная с Java 1.1, предоставляются как конкретные реализации. - person GOTO 0; 15.06.2014
comment
@GOTO0 Спасибо. Но в этом случае Number объявляется как класс abstract вместо interface, и под конкретной реализацией вы подразумеваете, что автор объявляет методы abstract concrete в классе abstract? Это понятно, но в случае, когда он (Number) был interface и допустим, что подкласс уже extend другого класса, это не сработает, верно? - person Unheilig; 15.06.2014
comment
@Unheilig нет, это не сработает. В этом случае рекомендуется создать новый интерфейс, расширяющий старый с помощью новых объявлений, которые станут доступны только для более нового кода. - person GOTO 0; 15.06.2014
comment
@Unheilig Я не могу найти ссылку на свое утверждение выше, но вот официальное руководство, объясняющее эту идею: docs.oracle.com/javase/tutorial/java/IandI/nogrow.html - person GOTO 0; 15.06.2014
comment
@GOTO0 Спасибо, интересно. Звучит нубски, но я не знал, что interface можно extend еще interface так. - person Unheilig; 15.06.2014

В Java 8 интерфейсы могут определять для этой цели методы по умолчанию.

person GOTO 0    schedule 15.06.2014