2008-10-07 3 views
8

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

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

ответ

17

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

+0

UnsupportedOperationException обычно является способом выхода, если только вы не знаете, что метод будет вызван в любом случае, и вы хотите сделать больше «no-op», и в этом случае возвращение нулевого или подобного - это лучшее, что вы можете сделать , – skaffman 2008-10-07 17:12:25

+0

хорошо ... кажется, вы ответили на свой вопрос там, Майк. – Sandman 2008-10-07 21:53:30

10

Это зависит от вашего делового случая. 2 варианта:

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

Обратите внимание, что библиотека Java идет по пути исключения в конкретном случае из read-only коллекций.


Ниже было отмечено, что UnsupportedOperationException является частью рамки java-коллекций. Если ваша ситуация за пределами коллекций, и семантика вас беспокоит, вы можете бросить свой собственный NotImplementedException, или если вы уже используете commons-lang, вы можете использовать theirs.

3

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

  1. ничего не делать.
  2. Выбросьте исключение.

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

2

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

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

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

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

5

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

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