2016-10-07 1 views
2

Планирует ли Java, что default method заменить на Abstract Class? Я не мог найти реальный случай использовать метод по умолчанию вместо абстрактного?Имеет ли Java план по умолчанию (java8) Подставить для абстрактного класса?

+0

Почему бы и нет? Подумайте о добавлении функциональности в интерфейс, не нарушая его разработчиков. – ChiefTwoPencils

+4

Вам нужно будет спросить этих прекрасных людей в Oracle. Я не думаю, что сообщество Stack Overflow может ответить на вопросы о том, какие планы Oracle могут иметь. –

+0

@DavidWallace, поэтому stackoverflow существует? правильно? Причина этой темы в том, что если абстрактный класс по-прежнему необходим после реализации метода по умолчанию, то с jaava8? –

ответ

5

Методы по умолчанию не могут заменить абстрактные классы, поскольку абстрактные классы могут (и часто) иметь поля. Интерфейсы могут содержать только поведение, а не состояние, которое вряд ли изменится в будущем, поскольку множественное наследование состояния в Java рассматривается (правильно или неправильно) как зло.

У них также могут быть методы final, что совсем другое, что вы не можете имитировать с помощью методов default.

В любом случае интерфейсы с методами по умолчанию напоминают traits, а не абстрактные классы, но совпадение не является совершенным. Использование интерфейсов как признаков - это то, что нужно сделать очень тщательно и зная ограничения, с которыми они сталкиваются. (Например, любой реализующий класс может переопределить метод default, потенциально разрушая признак.)

Подробнее об этом here.

+2

Java 9 будет иметь частные методы (как это делают абстрактные классы), хотя Java 8 этого не делает. –

+5

@Peter Lawrey: методы 'private' в интерфейсах помогают только обменяться кодами между разными всегда -' public' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' Это отличается от методов публикации с контролем доступа, т. Е. Объявляет их 'protected' или private-package. Обратите внимание, что поддержка 'private' методов в интерфейсах уже де-факто в Java 8, поскольку lambda выражения скомпилированы в' private' методы, это также относится к лямбда-выражениям, содержащимся в методах интерфейса 'default' или' static'. – Holger

+2

@Holger частные методы в интерфейсе позволят коду делиться между общедоступными методами и извлекать из них, чтобы упростить их. –

5

Одна из причин, по которой были введены методы по умолчанию в интерфейсах, заключалась в том, чтобы позволить добавлять новые методы к интерфейсам JDK.

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

8

Там нет таких планов, которые вы можете получить из сравнения уже задокументированы намерения, которые отличаются от последствий такого плана:

Stuart Marks writes:

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

...

Основной целью интерфейса Java является specify a contract, что любой класс может реализовать без изменения его положения в иерархии классов. Верно, что до Java 8 интерфейсы были чисто абстрактными. Однако это не является существенным свойством интерфейсов. Даже когда включены методы по умолчанию, интерфейс в его сердце все еще указывает контракт на класс реализации. Класс реализации может переопределять методы по умолчанию, поэтому класс по-прежнему полностью контролирует его реализацию. (Заметим также, что default methods cannot be final.)

и Brian Goetz writes:

Непосредственной причиной для добавления стандартных методов интерфейсов была поддержка эволюции интерфейса ...

Вот некоторые случаи использования, которые находятся в пределах целей проекта :

  • Интерфейс эволюции. Здесь мы добавляем новый метод к существующему интерфейсу, который имеет разумную реализацию по умолчанию с точки зрения существующих методов этого интерфейса. Примером может быть добавление метода forEach к Collection, где реализация по умолчанию записывается в терминах метода iterator().

  • "Необязательные" методы. Здесь разработчик интерфейса говорит: «Разработчики не должны реализовывать этот метод, если они хотят жить с ограничениями в функциональности, которые влекут за собой». Например, Iterator.remove получил значение по умолчанию, которое выбрасывает UnsupportedOperationException; так как подавляющее большинство реализаций Iterator имеют такое поведение, по умолчанию этот метод по существу является необязательным. (Если поведение от AbstractCollection было выражено по умолчанию на Collection, мы могли бы сделать то же самое для мутативных методов.)

  • Способы удобства. Это методы, которые строго для удобства, опять же обычно реализуются с точки зрения нестандартных методов для класса. Метод logger() в вашем первом примере является разумной иллюстрацией этого.

  • Комбинаторы. Это композиционные методы, которые создают новые экземпляры интерфейса на основе текущего экземпляра. Например, методы Predicate.and() или Comparator.thenComparing() являются примерами комбинаторов.

Обратите внимание, что они не нацелены на основной домен абстрактных классов, как обеспечение реализации скелета. Помимо technical differences, абстрактные классы семантически различаются, поскольку они несут проектные решения около , так как реализовать функциональность, интерфейс которой даже с использованием методов default не должен. Например. хорошо известным примером является интерфейс List, для которого существуют два принципиально различных абстрактных класса: AbstractList и AbstractSequentialList, а выбор подклассов либо реализация List совершенно другой не должен быть исключен интерфейсом. Таким образом, интерфейс List определяет контракт и не может быть заменой абстрактного класса, который обеспечивает конкретную базовую реализацию.

+0

Интересно, что как Маркс, так и Гётц упоминали об эволюции интерфейса и что Маркс назвал эту «главную цель». Я не могу не думать, что если бы это было правдой, они бы просто изменили язык, чтобы методы интерфейса не были реализованы в реализации интерфейса. Не реализованные методы могут просто ничего не делать и возвращать null (если их тип возврата является ссылочным типом) или правильный вкус нулевого или ложного (если их тип возврата является примитивным). Я не вижу, как такое изменение на языке сломает что угодно. И у меня было бы очень ... –

+0

... предпочел это для целого беспорядка «по умолчанию», который (1) просто попрошайничает, чтобы его неправильно использовали, (2) на самом деле значительно усложняет поиск «фактической реализации», метода в классе, который реализует множество интерфейсов и (3) не заставляют меня начинать с наследования алмазов. При всем уважении к @StuartMarks, я действительно не понимаю первый абзац его, который вы указали здесь. –

+0

@ Давид Уоллес: Я очень рад, что не сталкивался с такими «неуправляемыми» методами такого бедняка, которые на самом деле непригодны для использования, без возможности для кода клиента узнать. Задача поиска реализации так же просто, как нажимать на метод в среде IDE, а не на то, что это важно, так как вы должны разрабатывать контракт, независимо от того, где этот метод реализован, а «наследование алмазов» не является реальной проблемой поскольку язык запрещает двусмысленное наследование. И хотя эволюция интерфейса является важной целью, это * не * единственная цель. Рассмотрим [это] (http://stackoverflow.com/a/19998622/2711488) ... – Holger

6

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

Рассмотрим два различных способа использования класса или интерфейса в Java: как вызывающему или как subclasser. Вызывающий объект имеет ссылку на объект и может вызвать методы public и получить доступ к полям public через эту ссылку. Субклассист также может получать доступ, вызывать и переопределять protected членов суперкласса.Классы могут иметь protected членов, но интерфейсы не могут.

Общепринятый вопрос, похоже, что у нас есть методы по умолчанию, зачем нужны абстрактные классы? Метод по умолчанию является частью того, что интерфейс предоставляет абонентам. A protected метод класса не доступен для вызывающих абонентов; он доступен только для подклассов. Таким образом, если вы хотите разделить реализацию с подклассами, используйте класс (или абстрактный класс) и определите protected членов и полей.

Механизм protected позволяет классу общаться с подклассами, отличными от того, как он взаимодействует с вызывающими.

Но ОП задает противоположный вопрос: зачем использовать методы по умолчанию, предпочитая абстрактные классы? В ситуации, когда у вас действительно есть выбор (т. Е. Ваша абстракция не требует состояния или защищенных методов или любых вещей, которые абстрактные классы не имеют для этих интерфейсов), интерфейсы со стандартными методами гораздо менее сдерживают, чем абстрактные классы , Вы можете наследовать только один класс; вы можете наследовать многие интерфейсы. Таким образом, интерфейсы с методами по умолчанию могут вести себя как атрибуты без учета состояния или микшины, что позволяет наследовать поведение от нескольких интерфейсов.

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

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