Правильное поведение для методов интерфейса, которые не могут быть реализованы - PullRequest
8 голосов
/ 07 октября 2008

Если у меня есть класс, которому нужно реализовать интерфейс, но один или несколько методов этого интерфейса не имеют смысла в контексте этого конкретного класса, что мне делать?

Например, допустим, я реализую шаблон адаптера, в котором я хочу создать класс-оболочку, который реализует java.util.Map , оборачивая некоторый неизменный объект и выставляя его данные в виде пар ключ / значение , В этом случае методы put и putAll не имеют смысла, поскольку у меня нет способа изменить базовый объект. Итак, вопрос в том, что должны делать эти методы?

Ответы [ 5 ]

17 голосов
/ 07 октября 2008

Любой метод, который не может быть реализован в соответствии с семантикой интерфейса, должен выдавать UnsupportedOperationException .

10 голосов
/ 07 октября 2008

Это зависит от вашего бизнеса. 2 варианта:

Используйте то, что имеет больше смысла. Если вы ничего не делаете, вы не подчиняетесь контракту интерфейса. Однако создание исключения во время выполнения может нанести ущерб вызывающему коду. Таким образом, решение должно быть принято на основе того, как вы будете использовать класс. Другой вариант - использовать более простой или другой интерфейс, если это возможно.

Обратите внимание, что библиотека Java проходит маршрут исключения в конкретном случае коллекций только для чтения.


Ниже было отмечено, что UnsupportedOperationException является частью инфраструктуры коллекций Java. Если ваша ситуация находится за пределами коллекций, и семантика вас беспокоит, вы можете бросить свой собственный NotImplementedException или, если вы уже используете commons-lang, вы можете использовать их .
5 голосов
/ 07 октября 2008

Эта коллекция только для чтения, уже предоставленная Java, генерирует исключение UnsupportedOperationException во время операций записи, уже является неудачным взломом проекта. Классы коллекции должны были быть написаны с отдельными интерфейсами только для чтения и только для записи, которые оба наследуются полным интерфейсом чтения и записи. Тогда ты знаешь, что получаешь.

3 голосов
/ 07 октября 2008

Ваши два варианта действительно только:

  1. Ничего не делать.
  2. Брось исключение.

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

2 голосов
/ 07 октября 2008

Обратите внимание, что исключение UnsupportedOperationException допустимо только из-за особого свойства платформы Java Collections Framework, в котором реализациям разрешается "обманывать" реализацию части интерфейса, поскольку они неизменны.

Так что это нормально для метода put () (при условии, что все методы-мутаторы делают одно и то же), но карта, которая выбрасывает UnsupportedOperationException из метода size (), будет просто повреждена. Если вы пытаетесь реализовать карту, которая не знает, насколько она велика, у вас могут быть проблемы (хотя иногда вы можете вернуть Integer.MAX_VALUE).

Также обратите внимание, что в документации класса для UnsupportedOperationException говорится, что она является частью Java Collections Framework. Вне рамок коллекций исключение UnsupportedOperationException не ожидается и может привести к тому, что клиентский код просто не будет работать. Конечно, это RuntimeException, но только то, что вы можете выбросить его, не означает, что ваш метод будет работать, если он всегда работает.

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

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