Этот вопрос уже имеет ответ здесь:
В Java можно создать абстрактный класс, который содержит только абстрактные методы. С другой стороны, можно создать интерфейс, который объявляет те же методы. При этом можно ли использовать абстрактные классы вместо интерфейсов?
Не всегда:
Документы Составьте более подробное сравнение:
Абстрактные классы против интерфейсов
В отличие от интерфейсов, абстрактные классы могут содержать поля, которые не являются статическими и финальными, и они могут содержать реализованные методы. Такие абстрактные классы аналогичны интерфейсам, за исключением того, что они обеспечивают частичную реализацию, оставляя его подклассам для завершения реализации. Если абстрактный класс содержит только абстрактные декларации метода, он должен быть объявлен вместо этого интерфейс.
Несколько интерфейсов могут быть реализованы классами в любом месте классовой иерархии, независимо от того, связаны ли они друг с другом любым способом. Подумайте о сопоставимых или кложинах, например.
Сравнением, абстрактные классы чаще всего широко распространены, чтобы поделиться кусочками реализации. Один абстрактный класс подклассуется подобными классами, которые имеют много общего (реализованные части абстрактного класса), но также имеют некоторые различия (абстрактные методы).
Для этого можно использовать простой двойник.
double amount = 990.49;
double rounded = ((double) (long) (amount * 20 + 0.5)) / 20;
EDIT: для отрицательных чисел необходимо вычесть 0,5
-121--2229769-Другая идея состоит в том, чтобы использовать Apache Commons Lang для написания следующего кода:
StringUtils.join(myList);
Интерес заключается в том, что вы также можете предоставить разделитель, например:
StringUtils.join(myList, " ; ");
-121--3030969- Однако вряд ли когда - либо это будет хорошей идеей. В общем случае следует использовать правило
Другая «проблема» с использованием абстрактных классов заключается в том, что вы больше не можете реализовать миксины, то есть вы можете реализовать несколько интерфейсов, однако вы можете расширить только один абстрактный класс.
Абстрактные классы и интерфейсы дополняют.
Например, при создании API вы захотите представить интерфейсы клиенту, чтобы вы всегда могли полностью изменить реализацию, тогда как ему не нужно менять свой код, и пользователь не полагается на реализацию при построении с использованием вашего API. Но только на методах контрактов.
Тогда у вас будут абстрактные классы, частично реализующие эти интерфейсы, чтобы
Чтобы ответить на ваш вопрос, да, вы могли бы использовать абстрактный класс (не предоставляя никакой реализации) вместо интерфейса, но я бы учёл эту плохую практику:
Я бы больше выступал за использование абстрактных классов в ситуациях, когда Вы хотите обеспечить частичную реализацию класса, возможно, делегируя некоторое поведение конкретным реализациям подклассов.
Взгляд на интересную статью « Почему распространяется зло », чтобы получить представление о различиях между реализацией интерфейса и наследством класса (помимо очевидных многоограничных ограничений)
[Интерфейсы намного чище и легче. Абстрактные классы делают вас сильно зависимыми от них, так как вы не можете расширять другие классы.
Класс в java может наследовать от множества интерфейсов, но только от одного абстрактного класса.
Интерфейс не может определить код, в абстрактном классе можно определить код (т.е. поведение методов по умолчанию)
Здесь не хватает одного пункта в ответах - это идея , кто будет реализовывать интерфейс.
Если ваш компонент хочет вернуть экземпляры абстрактных типов вызывающим абонентам, где конкретные типы определены внутренне и скрыты от вызывающих абонентов, используйте интерфейс . И наоборот, если ваш компонент потребляет или принимает экземпляры абстрактных типов, которые должны быть реализованы его вызывающими абонентами , то абстрактные классы обычно являются лучшим вариантом .
Предвидение эволюции и поддержание бинарной совместимости указывает здесь на весы. С помощью абстрактного класса вы можете добавлять методы, и если вы предоставите базовую реализацию, то существующие реализации абстрактного класса будут продолжать работать нормально. С помощью интерфейса добавление метода нарушает бинарную совместимость, так как ни одна из существующих реализаций не может продолжать компиляцию должным образом без изменения определения нового метода.
В проекте Apache Cactus есть хорошее обсуждение о том, как решить эти задачи.