Расширение интерфейса для изменения контракта, но не API - PullRequest
0 голосов
/ 17 апреля 2019

(Я не уверен, что терминология заголовков верна.)

Предположим, я пытаюсь создать некоторую абстракцию для читаемых, доступных для записи и доступных для чтения и записи "свойств". В зависимости от ситуации, я мог бы хотеть принять только читаемые свойства, только доступные для записи свойства или оба (доступные для чтения и записи). Однако предположим, что я хочу, чтобы оба типа свойств выводили свои основные методы из одного и того же супертипа, но я также хочу поддерживать безопасность типов (например, если я запрашиваю читаемое свойство, я хочу быть уверен, что получу читаемое свойство).

Вот как может выглядеть Property суперинтерфейс:

public interface Property {
    // Readable property core methods

    /**
     * Blah blah...
     * @throws UnsupportedOperationException if this property is not readable.
     */
    X readAsX();
    ...

    // Writable property core methods

    /**
     * Blah blah...
     * @throws UnsupportedOperationException if this property is not writable.
     */
    void writeX(X value);
    ...
}

Важно отметить, что указывается выбрасывать UnsupportedOperationException в зависимости от ситуации, если Property не доступен для чтения / записи.

Теперь, будет ли следующий способ подходящим для определения ReadableProperty? (WritableProperty будет определен аналогично.)

public interface ReadableProperty extends Property {
    // Readable property core methods

    /**
     * Blah blah...
     * Not allowed to throw UnsupportedOperationException: must be readable!
     */
    X readAsX();
    ...

    // Writable property core methods

    /**
     * Always throws UnsupportedOperationException: this property is not writable.
     */
    default void writeX(X value) {
        throw new UnsupportedOperationException();
    }
    ...
}

Обратите внимание, что новые методы не были добавлены; все, что изменилось, это то, что существующие методы имеют более строгую спецификацию. Это подходящий дизайн для описанной ситуации?

(Примечание: этот сценарий вымышленный. Меня больше интересует идея, чем ее конкретное применение.)

Ответы [ 2 ]

1 голос
/ 17 апреля 2019

У меня был бы абстрактный класс Property, содержащий общие операции чтения и записи, ReadProperty, расширяющий этот абстрактный класс и реализующий операцию Read, и WriteProperty, расширяющий этот абстрактный класс и реализующий операцию Read.

Имея неподдерживаемую операцию в вашем интерфейсе, вы нарушаете принцип подстановки Лискова.Взгляните на принципы SOLID.

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

1 голос
/ 17 апреля 2019

Почему бы вам просто не использовать два абстрактных класса, реализующих только один метод каждый?

public abstract class ReadableProperty implements Property {
// Readable property core methods
// Writable property core methods

/**
 * Always throws UnsupportedOperationException: this property is not writable.
 */
@Override
final void writeX(X value) {
    throw new UnsupportedOperationException();
}

}

На самом деле вы реализуете метод интерфейса, а не определяете поведение по умолчанию для вновь введенной подписи в интерфейсе (это основная причина, по которой был применен модификатор по умолчанию)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...