2014-11-12 8 views
5

Я пытаюсь придумать полный ответ на:Java 8 - интерфейсы с методами по умолчанию против абстрактных классов

«почему/когда использовать абстрактный класс, а не интерфейс

и ищет подтверждения/предложения по следующему.

Ответ на это,

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

Еще одна веская причина для использования абстрактного класса заключается в том, что существует четкая логическая иерархия среди типов. Абстрактный класс использует для организации иерархию , заставляя, будучи абстрактным классом, а не конкретным, создание объектов только на конкретных классах ниже в этой иерархии, где они полностью определены и, следовательно, имеют смысл. "

Затем, в связи с этим, приходит Q:

«, так как Java 8, интерфейсы могут определить default method реализации Почему я не писал бы по умолчанию метод (ы) в интерфейсе вместо. ? абстрактный класс, который реализует этот метод (ы) "

ответ на этот вопрос будет:

« Одна из причин: все методы интерфейса являются общедоступными, членами поля являются все константы (окончательный & публичный). Вы можете ограничить права доступа к методам и/или заставить их работать с непостоянным состоянием.

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

Остальные причины такие же, как и в пред-Java 8 выше. ? "

Кроме них выше, почему бы я лучше пойти для абстрактного класса, чем интерфейс, особенно теперь, когда у меня есть методы интерфейсных по умолчанию, так как Java 8

Пожалуйста, обратите внимание: я видел Java 8 default methods vs. non-abstract methods in abstract classes и Interface with default methods vs Abstract class in Java 8 наряду с некоторым другим полезным обсуждением. Это Вопрос скорее о , почему выбрал абстрактный класс через интерфейс, чем наоборот.

ТИА.

+3

Хотя я думаю, что это правильный вопрос, я не уверен, что он является ontopic для StackOverflow. Вы можете попробовать [Programmers.SE] (programers.stackexchange.com). – nhaarman

ответ

5

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

  • Тип ясности. Вы можете расширить только один класс. Это дает более четкое представление о том, как ваш объект использует его.
  • Алмазная проблема. Вы должны реализовать все методы по умолчанию в интерфейсе, чтобы избежать проблемы с алмазом. Если интерфейс представляет собой Коллекции, это может быть огромной болью, так как их миллиард. С абстрактным классом вы переписываете только то, что вам нужно
  • В Java 8 есть лямбда-выражения, а старая процедура прохождения по интерфейсу с помощью метода реализации была узурпирована. Тем не менее, когда вы видите, интерфейс с методом по умолчанию, это может интерпретироваться таким образом, вы, возможно, не намерены

Вот что Oracle должен сказать по этой теме:

Какой вы должны использовать, абстрактные классы или интерфейсов? Рассмотрите возможность использования абстрактных классов, если любой из этих утверждений относится к вашей ситуации:

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

В этой статье Orace защищает различие между этими двумя системами типа https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html

EDIT Для уточнения «проблемный алмаз» пуля проблема описана здесь (и во многих других местах)

Проблема возникает, когда вы наследуете от двух мест, объявляющих один и тот же метод, и вам нужно выбрать один при разрешении функции ca LL. Это никогда не было проблемой в Java 7, поскольку вы могли только расширить один класс, а интерфейсы не имели методов.

Разрешающая тактика сейчас немного сложнее, но и здесь есть хорошее описание этого: (от http://blog.loxal.net/2013/05/java-8-default-interface.html)

Для решения этой проблемы алмазной существует преимущество, в каком порядке используется реализации : только если класс реализует все стандартные/ необязательные методы своих интерфейсов, код может быть скомпилирован и используются реализации этого класса. В противном случае компилятор пытается выполнить для исправления недостающих реализаций с использованием интерфейса по умолчанию . И если есть несколько стандартных реализаций метода , возникает проблема с алмазом, и компилятор отклоняет компиляцию . Кроме того, если класс реализует метод интерфейса по умолчанию , реализация класса будет использоваться вместо реализации по умолчанию интерфейсов .

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

+0

Вы можете уточнить проблему алмаза – Roam

1

короткий ответ:

  1. класс может проходить ровно один класс.
  2. класс может реализовать любое количество интерфейсов.
7

Интерфейсы со стандартными методами могут определять поведение, тогда как абстрактные классы могут иметь состояние.

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

Другой вариант использования абстрактных классов - это если вы хотите переопределить некоторые из методов Object, таких как equals или toString. Это невозможно сделать с помощью методов по умолчанию.

0

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

  • Абстрактный класс может иметь конструкторов но интерфейс не может.
  • Аннотация класс может наследовать только из одного класса и может реализовывать интерфейсы, но интерфейс может расширять только несколько интерфейсов.

  • Абстрактный класс атрибуты также могут быть кратковременными/летучий

  • Абстрактный класс методы также могут быть окончательными/статический/синхронизировано/родной

  • Интерфейс методы также могут быть по умолчанию или static с реализацией. (не может быть как стандартным, так и статическим.)

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