Насколько я понимаю, если вы реализуете интерфейс на java, методы, указанные в этом интерфейсе, должны использоваться подклассами, реализующими указанный интерфейс.
Я заметил, что в некоторых интерфейсах, таких как интерфейс Collection, есть методы, которые комментируются как необязательные, но что именно это означает? Это меня немного сбило с толку, поскольку я думал, что потребуются все методы, указанные в интерфейсе?
Ответы:
Кажется, здесь очень много путаницы в ответах.
Язык Java требует, чтобы каждый метод в интерфейсе реализовывался каждой реализацией этого интерфейса. Период. Из этого правила нет исключений. Сказать «Коллекции - исключение» предполагает очень нечеткое понимание того, что здесь действительно происходит.
Важно понимать, что существует два уровня соответствия интерфейсу:
Что может проверить язык Java. Это в значительной степени сводится к следующему: есть ли какая-то реализация для каждого из методов?
Фактически выполняю договор. То есть выполняет ли реализация то, что указано в документации по интерфейсу?
Хорошо написанные интерфейсы будут включать документацию, точно объясняющую, что ожидается от реализации. Ваш компилятор не может проверить это за вас. Вам нужно читать документы и делать то, что они говорят. Если вы не сделаете то, что сказано в контракте, то у вас будет реализация интерфейса в том, что касается компилятора , но это будет дефектная / недействительная реализация.
При разработке API коллекций Джошуа Блох решил, что вместо очень детализированных интерфейсов для различения различных вариантов коллекций (например, читаемых, доступных для записи, произвольного доступа и т. Д.) У него будет только очень грубый набор интерфейсов, в первую очередь
Collection
,List
,Set
иMap
, а затем документировать определенные операции , как « по желанию». Это было сделано, чтобы избежать комбинаторного взрыва, который может произойти из-за мелкозернистых интерфейсов. Из FAQ по дизайну Java Collections API :Когда методы в API коллекций задокументированы как «необязательные операции», это не означает, что вы можете просто оставить реализацию метода в реализации, и не означает, что вы можете использовать пустое тело метода (например, многие из им нужно вернуть результат). Скорее, это означает, что допустимый вариант реализации (тот, который по-прежнему соответствует контракту) - это бросить файл
UnsupportedOperationException
.Обратите внимание, что, поскольку
UnsupportedOperationException
это a,RuntimeException
вы можете выбросить его из любой реализации метода, если это касается компилятора. Например, вы можете выбросить его из реализацииCollection.size()
. Однако такая реализация нарушила бы контракт, поскольку в документацииCollection.size()
не сказано, что это разрешено.В сторону: подход, используемый Java Collections API, несколько противоречив (однако, вероятно, меньше, чем когда он был впервые представлен). В идеальном мире интерфейсы не имели бы дополнительных операций, вместо этого использовались бы мелкозернистые интерфейсы. Проблема в том, что Java не поддерживает ни предполагаемые структурные типы, ни типы пересечений, поэтому попытки делать что-то «правильным путем» в конечном итоге становятся чрезвычайно громоздкими в случае коллекций.
источник
There are no exceptions to this rule
. Хотите знать, почему этот ответ не помечен как принятый. Другие хороши, но вы дали более чем достаточно.Foo
, который не реализуетсяRunnable
с помощью общедоступного методаvoid run()
. Теперь создайте класс,Bar
которыйextends Foo
иimplements Runnable
не перекрываетrun
. Он по-прежнему реализует метод, хотя и косвенно. Точно так же реализация метода по умолчанию остается реализацией.remove
была предоставлена реализация по умолчанию. Если вы не реализуете его, ваш класс получит реализацию по умолчанию. Два других упомянутых вами метода не имеют реализации по умолчанию.Чтобы скомпилировать реализующий (не абстрактный) класс для интерфейса - все методы должны быть реализованы.
Однако , если мы думаем о методе, реализация которого представляет собой простую выдачу исключения, как о «нереализованном» (как некоторые методы в
Collection
интерфейсе), тогдаCollection
интерфейс является исключением в этом случае, а не обычным случаем. Обычно реализующий класс должен (и будет) реализовывать все методы.«Необязательный» в коллекции означает, что реализующий класс не должен «реализовывать» (в соответствии с приведенной выше терминологией) его, и он просто выбрасывает
NotSupportedException
).Хороший пример -
add()
метод для неизменяемых коллекций - бетон просто реализует метод, который ничего не делает, кроме бросанияNotSupportedException
В этом случае
Collection
это делается для предотвращения беспорядочных деревьев наследования, которые сделают программистов несчастными, но в большинстве случаев эта парадигма не рекомендуется, и ее следует по возможности избегать.Обновить:
Начиная с java 8, был введен метод по умолчанию .
Это означает, что интерфейс может определять метод, включая его реализацию.
Это было добавлено для того, чтобы позволить добавлять функциональные возможности в интерфейсы, при этом поддерживая обратную совместимость для частей кода, которым не нужны новые функциональные возможности.
Обратите внимание, что метод по-прежнему реализуется всеми классами, которые его объявляют, но с использованием определения интерфейса.
источник
Интерфейс в Java просто объявляет контракт на реализацию классов. Все методы в этом интерфейсе должны быть реализованы, но реализующие классы могут оставить их нереализованными, то есть пустыми. В качестве надуманного примера
Теперь я оставил
doSomethingElse()
нереализованным, оставив его свободным для реализации подклассами. Это необязательно.Однако, если вы говорите об интерфейсах Collection, как говорили другие, они являются исключением. Если некоторые методы остаются нереализованными и вы вызываете их, они могут вызывать
UnsupportedOperationException
исключения.источник
Необязательные методы в интерфейсе Collection означают, что реализации метода разрешено генерировать исключение, но оно должно быть реализовано в любом случае. Как указано в документации :
источник
new Runnable ( ) { @ Override public void run ( ) { throw new UnsupportedOperationException ( ) ; } }
:;add((T)null)
может быть действительным в одном случае, но не в другом. То есть здесь говорится о необязательных исключениях / поведении и для аргументов («ограничения на элементы» ... «недопустимый элемент« ... »исключения, помеченные как необязательные») и не рассматриваются необязательные методы .Все методы должны быть реализованы для компиляции кода (кроме тех, которые
default
реализованы в Java 8+), но реализация не обязана делать что-либо функционально полезное. В частности, это:UnsupportedOperationException
(или подобное)Последний подход часто применяется в классах коллекций - все методы по-прежнему реализованы, но некоторые из них могут вызывать исключение, если вызываются во время выполнения.
источник
На самом деле меня вдохновляет SurfaceView.Callback2. Я думаю это официальный способ
Если вашему классу не нужно реализовывать необязательные методы, просто «реализует обратный вызов». Если вашему классу необходимо реализовать необязательные методы, просто «реализует CallbackExtended».
Простите за дерьмо английский.
источник
В Java 8 и более поздних версиях ответ на этот вопрос по-прежнему актуален, но теперь он более детализирован.
Во-первых, эти утверждения из принятого ответа остаются верными:
Итак, что нового в Java 8? Говоря о «необязательных методах» , теперь уместно любое из следующего:
1. Метод, реализация которого не является обязательной по контракту.
«Третье утверждение» говорит, что методы абстрактного интерфейса должны быть реализованы всегда, и это остается верным в Java 8+. Однако, как и в Java Collections Framework, некоторые абстрактные методы интерфейса можно описать как «необязательные» в контракте.
В этом случае автор, реализующий интерфейс, может отказаться от реализации метода. Однако компилятор будет настаивать на реализации, и поэтому автор использует этот код для любых дополнительных методов, которые не нужны в конкретном классе реализации:
В Java 7 и ранее это был единственный вид «необязательного метода», т. Е. Метод, который, если он не реализован, вызывал исключение UnsupportedOperationException. Это поведение обязательно указывается в контракте интерфейса (например, дополнительные методы интерфейса Java Collections Framework).
2. Метод по умолчанию, повторная реализация которого не является обязательной.
В Java 8 появилась концепция методов по умолчанию . Это методы, реализация которых может быть обеспечена самим определением интерфейса. Как правило, можно предоставить методы по умолчанию только тогда, когда тело метода может быть написано с использованием других методов интерфейса (т. Е. «Примитивов»), и когда
this
может означать «этот объект, класс которого реализовал этот интерфейс».Метод по умолчанию должен выполнять контракт интерфейса (как и любая другая реализация метода интерфейса). Следовательно, определение реализации метода интерфейса в классе реализации остается на усмотрение автора (если поведение соответствует его или ее цели).
В этой новой среде Java Collections Framework может быть переписан как:
Таким образом, «необязательный» метод
add()
имеет поведение по умолчанию, выбрасывающее исключение UnsupportedOperationException, если реализующий класс не обеспечивает собственного нового поведения, что именно то, что вы хотели бы иметь, и которое соответствует контракту для List. Если автор пишет класс, который не позволяет добавлять новые элементы в реализацию List, реализация неadd()
является обязательной, поскольку поведение по умолчанию - именно то, что необходимо.В этом случае "третье утверждение" выше по-прежнему остается в силе, потому что метод был реализован в самом интерфейсе.
3. Метод, возвращающий
Optional
результат.Последний новый вид необязательного метода - это просто метод, который возвращает
Optional
.Optional
Класс обеспечивает явно более объектно-ориентированный способ борьбы сnull
результатами.В свободном стиле программирования, который обычно наблюдается при кодировании с использованием нового Java Streams API, нулевой результат в любой момент вызывает сбой программы с исключением NullPointerException.
Optional
Класс обеспечивает механизм для возврата результатов неопределенной коды клиента таким образом , что дает возможность свободно стиль , не вызывая клиентский код аварию.источник
Если мы рассмотрим код AbstractCollection.java в grepCode, который является классом-предком для всех реализаций коллекций, это поможет нам понять значение необязательных методов. Вот код для метода add (e) в классе AbstractCollection. Метод add (e) является необязательным в соответствии с интерфейсом коллекции
Необязательный метод означает, что он уже реализован в классах-предках и при вызове выдает исключение UnsupportedOperationException. Если мы хотим сделать нашу коллекцию изменяемой, мы должны переопределить необязательные методы в интерфейсе коллекции.
источник
Ну, эта тема была затронута ... да ... но думаю, не хватает одного ответа. Я говорю о "методах по умолчанию" интерфейсов. Например, представим, что у вас есть класс для закрытия чего-либо (например, деструктора или чего-то подобного). Допустим, у него должно быть 3 метода. Назовем их «doFirst ()», «doLast ()» и «onClose ()».
Итак, мы говорим, что хотим, чтобы любой объект этого типа, по крайней мере, реализовал "onClose ()", но остальные не обязательны.
Вы можете понять это, используя «Методы по умолчанию» интерфейсов. Я знаю, что в большинстве случаев это отрицает причину создания интерфейса, но если вы разрабатываете фреймворк, это может быть полезно.
Итак, если вы хотите реализовать это таким образом, это будет выглядеть следующим образом
Что теперь произойдет, если вы, например, реализуете это в классе под названием «Test», компилятор будет прекрасно справляться со следующим:
с выходом:
или
с выходом:
Возможны все комбинации. Все, что имеет значение «default», может быть реализовано, но не должно быть реализовано, однако все, что без него, должно быть реализовано.
Надеюсь, что теперь я отвечу не совсем неправильно.
Всем хорошего дня!
[edit1]: Обратите внимание: это работает только в Java 8.
источник
Я искал способ реализовать интерфейс обратного вызова, поэтому реализация дополнительных методов была необходима, поскольку я не хотел реализовывать каждый метод для каждого обратного вызова.
Итак, вместо использования интерфейса я использовал класс с пустой реализацией, например:
И вы можете установить переменную-член CallBack следующим образом:
тогда назовите это так.
Таким образом, вам не нужно будет беспокоиться о реализации всех методов для каждого обратного вызова, а переопределить только те, которые вам нужны.
источник
Хотя он не отвечает на вопрос OP, стоит отметить, что в Java 8 добавление методов по умолчанию к интерфейсам на самом деле выполнимо .
default
Ключевое слово помещается в подписи метода качестве интерфейса будет приводить к классу , имеющему возможность переопределить метод, но не требовать его.источник
Учебник Oracle по коллекциям Java:
источник