В чем разница между интерфейсом и абстрактным классом?


1753

В чем именно разница между интерфейсом и абстрактным классом?


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

5
Этот вопрос также может помочь понять концепцию интерфейсов stackoverflow.com/q/8531292/1055241
gprathour

6
Я удалил тег PHP из этого вопроса, поскольку почти ни один из ответов не зависит от языка, а сам вопрос не зависит от языка.
Брайс

2
Когда-то в C ++ интерфейс представлял собой чистый абстрактный базовый класс со всеми реализациями метода = 0. Если у одного метода не было = 0, то у него есть реализация, и абстрактная база больше не является чистой и больше не является интерфейсом. , Я думаю, что у VMT меньше косвенности, когда множественное наследование использует только чистые абстрактные базы, но я не помню, как они выглядят, слишком долго.
Джим

Ответы:


2255

Интерфейсы

Интерфейс - это контракт : человек, пишущий интерфейс, говорит: « Эй, я принимаю вещи, выглядящие так », а человек, использующий интерфейс, говорит: « Хорошо, класс, который я пишу, выглядит так ».

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

Например (псевдокод):

// I say all motor vehicles should look like this:
interface MotorVehicle
{
    void run();

    int getFuel();
}

// My team mate complies and writes vehicle looking that way
class Car implements MotorVehicle
{

    int fuel;

    void run()
    {
        print("Wrroooooooom");
    }


    int getFuel()
    {
        return this.fuel;
    }
}

Реализация интерфейса потребляет очень мало ресурсов ЦП, потому что это не класс, а просто набор имен, и, следовательно, нет дорогого поиска. Это здорово, когда это важно, например, во встроенных устройствах.


Абстрактные классы

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

Абстрактные классы очень похожи на интерфейсы, но у них есть нечто большее: вы можете определить поведение для них. Это больше о человеке, который говорит: « Эти классы должны выглядеть так, и у них есть это общее, так что заполняйте пробелы! ».

Например:

// I say all motor vehicles should look like this:
abstract class MotorVehicle
{

    int fuel;

    // They ALL have fuel, so lets implement this for everybody.
    int getFuel()
    {
         return this.fuel;
    }

    // That can be very different, force them to provide their
    // own implementation.
    abstract void run();
}

// My teammate complies and writes vehicle looking that way
class Car extends MotorVehicle
{
    void run()
    {
        print("Wrroooooooom");
    }
}

Реализация

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

В Java это правило строго соблюдается, в то время как в PHP интерфейсы являются абстрактными классами без объявленного метода.

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

Как обычно в программировании, есть теория, практика и практика на другом языке :-)


6
Ключевой момент в отношении интерфейсов заключается не столько в том, что они говорят о том, что делает класс, но в том, чтобы позволить объектам, которые могут Wizzle, стать полезными для кода, который нуждается в Wizzler. Обратите внимание, что во многих случаях ни тот, кто пишет то, что может Wizzle, ни тот, кому нужен Wizzler, не будет тем, кто пишет интерфейс.
суперкат

187
Я не думаю, что потребление ресурсов процессора является наиболее важным моментом на интерфейсах.
Дэн Лугг

5
@ e-удовлетворительно Можете ли вы объяснить свою точку зрения на использование процессора? Почему абстрактный класс как класс увеличивает загрузку процессора? О каком поиске вы здесь говорите?
Компьютерщик

36
@ e-Satin В Java 8 вы можете определять методы по умолчанию в интерфейсах, что эквивалентно наличию неабстрактных методов в абстрактных классах. С этим добавлением я больше не вижу реальной разницы между абстрактными классами и интерфейсом, кроме того факта, что я должен использовать интерфейсы, потому что классы могут реализовывать несколько интерфейсов, но могут наследовать только один класс
Ogen

23
Я думаю, что сравнение между interfaceи classиз Head First Javaярко, чтоA class defines who you are, and an interface tells what roles you could play
LittleLittleQ

872

Основные технические различия между абстрактным классом и интерфейсом :

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

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

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

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

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

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


123
Я думаю, что это лучший ответ, потому что он подчеркивает все ключевые различия. пример на самом деле не нужен.
Джошуа К

4
И обычно с классами вы можете создать экземпляр объекта из него в отличие от абстрактных классов, которые CANNOTсоздаются.
SASM

Я думал, что класс, который реализует интерфейс, должен определить все методы в интерфейсе?
Jiazzy user

@Jiazzyuser Если абстрактный класс реализует интерфейс, он не должен фактически определять методы интерфейса. Это требование может быть отложено до наследования / дочерних конкретных классов. Однако конкретный класс должен реализовывать все методы интерфейса, которые не реализованы его родительским классом. Я добавлю пример, чтобы проиллюстрировать этот момент.
Джастин Джонсон

5
«При наследовании абстрактного класса дочерний класс должен определять абстрактные методы, тогда как интерфейс может расширять другой интерфейс, и методы не должны быть определены». - Это неправда. Так же, как интерфейс может расширять интерфейс без определения методов, абстрактный класс может наследовать абстрактный класс без определения методов.
Ник

141

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

введите описание изображения здесь Взято из:

http://www.dotnetbull.com/2011/11/difference-between-abstract-class-and.html

http://www.dotnetbull.com/2011/11/what-is-abstract-class-in-c-net.html http://www.dotnetbull.com/2011/11/what-is-interface-in -с-net.html


17
Вы должны сказать, к какому языку это относится («Абстрактный класс не поддерживает множественное наследование» далеко не всегда правдиво)
Бен Фойгт

Последнее сравнение сбивает с толку согласно таблице! Методы в интерфейсе не могут быть статическими, но переменные являются статическими. Final Реализованные методы в абстрактном классе могут быть статическими
realPK

8
Элемент интерфейса должен быть статическим окончательным. Последнее утверждение неверно.
Джавад Зеб

Я думаю, что «функциональность» в этом ответе означает «реализация». Не уверен, что означает «поведение» - может быть, «подписи»?
LarsH

2
Какой здесь язык программирования? C #?
Питер Мортенсен

80

Объяснение можно найти здесь: http://www.developer.com/lang/php/article.php/3604111/PHP-5-OOP-Interfaces-Abstract-Classes-and-the-Adapter-Pattern.htm

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

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

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


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

1
Правда, для PHP это действительно лучший ответ. Но из текстового блоба получить труднее, чем из простого фрагмента.
E-Удовлетворение

Из предоставленных вами определений они выглядят одинаково, за исключением одной детали: интерфейс является на 100% абстрактным, а абстрактный класс частично абстрактным и может иметь некоторые реализации методов (возможно, все методы могут иметь реализации?).
jww

41

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

Проще говоря, я хотел бы сказать:

интерфейс: для реализации контракта несколькими несвязанными объектами

абстрактный класс: для реализации одинакового или разного поведения среди нескольких связанных объектов

Из документации Oracle

Рассмотрите возможность использования абстрактных классов, если:

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

Рассмотрите возможность использования интерфейсов, если:

  1. Вы ожидаете, что несвязанные классы будут реализовывать ваш интерфейс. Например, многие несвязанные объекты могут реализовать Serializableинтерфейс.
  2. Вы хотите указать поведение определенного типа данных, но не беспокоитесь о том, кто реализует его поведение.
  3. Вы хотите воспользоваться множественным наследованием типа.

абстрактный класс устанавливает связь «есть» с конкретными классами. Интерфейс предоставляет возможность «имеет» для классов.

Если вы ищете в Javaкачестве языка программирования, вот еще несколько обновлений:

Java 8 в некоторой степени сократила разрыв между классами interfaceи abstractклассами, предоставив функцию defaultметода. Интерфейс не имеет реализации для метода , более не действителен в настоящее время.

Обратитесь к этой странице документации для получения более подробной информации.

Посмотрите на этот вопрос SE для примеров кода, чтобы лучше понять.

Как мне объяснить разницу между интерфейсом и абстрактным классом?


38

Некоторые важные отличия:

В форме таблицы:

разница

Как заявил Джо из javapapers :

1. Основное различие заключается в том, что методы интерфейса Java неявно абстрактны и не могут иметь реализации. Абстрактный класс Java может иметь методы экземпляров, которые реализуют поведение по умолчанию.

2. Переменные, объявленные в интерфейсе Java, по умолчанию являются окончательными. Абстрактный класс может содержать неконечные переменные.

3. Члены Java-интерфейса являются публичными по умолчанию. Абстрактный класс Java может иметь обычные разновидности членов класса, такие как private, protected и т. Д.

4. Java-интерфейс должен быть реализован с использованием ключевого слова «Implements»; Абстрактный класс Java должен быть расширен с помощью ключевого слова «extends».

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

6. Java-класс может реализовывать несколько интерфейсов, но он может расширять только один абстрактный класс.

7. Интерфейс абсолютно абстрактный и не может быть создан; Абстрактный класс Java также не может быть создан, но может быть вызван, если существует main ().

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


3
Я отредактировал ваш ответ, чтобы обеспечить правильную атрибуцию. Вы не можете просто оставить ссылку внизу вашего ответа. Вы должны также процитировать весь язык, который был скопирован из другого источника. Кроме того, если эта таблица была взята откуда-то, вы должны четко указать, откуда она.
Брэд Ларсон

Пожалуйста, упомяните также о C ++ ... хотя в C ++ нет ключевого слова "interface" как такового, но это также часто задаваемый Qn regd C ++.
cbinder

@cbinder: в c ++ нет ключевого слова interface. Для различия в c ++, пожалуйста, обратитесь к 1. tutorialspoint.com/cplusplus/cpp_interfaces.htm 2. tutorialspoint.com/cplusplus/cpp_interfaces.htm
softmage99

@MageshBabu Возможно, определение функции в классе, содержащем чисто виртуальную функцию, делает ее абстрактным классом, а не интерфейсом
cbinder

2
С Java 8 различия теперь меньше. Проверьте обновленные различия здесь: journaldev.com/1607/…
Pankaj

31

Суть в том, что:

  • Аннотация является объектно-ориентированной . Он предлагает основные данные, которые должен иметь «объект», и / или функции, которые он должен выполнять. Он касается основных характеристик объекта: что он имеет и что он может сделать. Следовательно, объекты, которые наследуются от одного и того же абстрактного класса, имеют общие характеристики (обобщение).
  • Интерфейс ориентирован на функциональность . Он определяет функциональные возможности, которые должен иметь объект. Независимо от того, что это за объект, пока он может выполнять эти функции, которые определены в интерфейсе, это нормально. Это игнорирует все остальное. Объект / класс может содержать несколько (групп) функциональных возможностей; следовательно, класс может реализовать несколько интерфейсов.

Спасибо, теперь мы получаем хороший отклик на высоком уровне. Забавно, насколько глубоко в комментарии вы должны зайти, чтобы найти более понятный ответ.
Андрей

1
Другие ответы слишком технические. Это приближается к тому, что я считаю «правильным» ответом. Весь смысл ООП заключается в семантике, и то, являются ли открытые методы получения закрытыми вложенными классами посредством дорогостоящих поисков ЦП, в значительной степени не имеет значения
Sentinel

26

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

Если вы хотите полиморфное поведение для классов, которые совершенно не связаны, используйте интерфейс.


24

Я строю здание из 300 этажей

План здания интерфейс

  • Например, Сервлет (I)

Здание построено до 200 этажей - частично завершено --- аннотация

  • Частичная реализация, например, универсальный и HTTP-сервлет

Строительство здания завершено- бетон

  • Полная реализация, например, собственного сервлета

Интерфейс

  • Мы ничего не знаем о реализации, только требования. Мы можем пойти на интерфейс.
  • Каждый метод является публичным и абстрактным по умолчанию
  • Это 100% чистый абстрактный класс
  • Если мы объявляем публичным, мы не можем объявить частным и защищенным
  • Если мы объявляем абстрактный, мы не можем объявить окончательный, статический, синхронизированный, строгий и нативный
  • У каждого интерфейса есть public, static и final
  • Сериализация и переходные процессы не применимы, потому что мы не можем создать экземпляр для в интерфейсе
  • Энергонезависимый, потому что он окончательный
  • Каждая переменная является статической
  • Когда мы объявляем переменную внутри интерфейса, нам нужно инициализировать переменные при объявлении
  • Экземпляр и статический блок не допускаются

Аннотация

  • Частичная реализация
  • У него есть абстрактный метод. Кроме того, он использует бетон
  • Нет ограничений для модификаторов метода абстрактного класса
  • Нет ограничений для модификаторов переменных абстрактного класса
  • Мы не можем объявить другие модификаторы, кроме абстрактных
  • Нет ограничений на инициализацию переменных

Взято с сайта DurgaJobs


У абстрактного класса может быть конструктор
Вимал Кришна

4
Я полностью не согласен с этим мнением. План представляет собой совершенно другую концепцию «интерфейса». План больше похож на статическую модель или спецификацию проекта для конкретной реализации. Он ближе к «классу», так как проект может быть создан несколько раз через его конструктор, но даже это не достаточно близко, поскольку «класс» также содержит спецификацию того, как построить (ctor), и средства для выполнения так. Интерфейс как концепция предназначен для представления некоторого поведения, такого как нагрев / охлаждение, которое может быть применено к ряду вещей, например, к зданиям, печам и т. Д.
Sentinel

18

Давайте снова поработаем над этим вопросом:

Первое, что вам нужно знать, это то, что 1/1 и 1 * 1 дают одинаковые результаты, но это не означает, что умножение и деление одинаковы. Очевидно, у них хорошие отношения, но учтите, что вы оба разные.

Я укажу основные отличия, а остальное уже объяснили:

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

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


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

«математическая метафора бесполезна», почему вы так думаете?
Дхананджай

12

Это довольно просто на самом деле.

Вы можете думать об интерфейсе как о классе, которому разрешено иметь только абстрактные методы и ничего больше.

Таким образом, интерфейс может только «объявлять» и не определять поведение, которое должен иметь класс.

Абстрактный класс позволяет вам как объявлять (используя абстрактные методы), так и определять (используя полные реализации методов) поведение, которое должен иметь класс.

А обычный класс позволяет вам только определять, а не объявлять поведение / действия, которые должен иметь класс.

Одна последняя вещь,

В Java вы можете реализовать несколько интерфейсов, но вы можете расширить только один (абстрактный класс или класс) ...

Это означает, что наследование определенного поведения ограничено, чтобы разрешить только одно на класс ... то есть, если вы хотели, чтобы класс, инкапсулирующий поведение из классов A, B и C, вам нужно было бы сделать следующее: класс A расширяет B, класс C расширяет A .. Немного о способе иметь множественное наследование ...

Интерфейсы с другой стороны, вы могли бы просто сделать: интерфейс C реализует A, B

Таким образом, в действительности Java поддерживает множественное наследование только в «объявленном поведении», то есть в интерфейсах, и только в единственном наследовании с определенным поведением ... если только вы не выполните описанный мной способ ...

Надеюсь, это имеет смысл.


11

Сравнение интерфейса и абстрактного класса неверно. Вместо этого должно быть два других сравнения: 1) интерфейс против класса и 2) абстрактный против финального класса .

Интерфейс против Класса

Интерфейс - это контракт между двумя объектами. Например, я почтальон, а ты посылка для доставки. Я ожидаю, что вы знаете свой адрес доставки. Когда кто-то дает мне посылку, он должен знать ее адрес доставки:

interface Package {
  String address();
}

Класс - это группа объектов, которые подчиняются договору. Например, я ящик из группы «Ящик» и подчиняюсь договору, требуемому Почтальоном. В то же время я подчиняюсь другим контрактам:

class Box implements Package, Property {
  @Override
  String address() {
    return "5th Street, New York, NY";
  }
  @Override
  Human owner() {
    // this method is part of another contract
  }
}

Аннотация против Финал

Абстрактный класс - это группа незавершенных объектов. Их нельзя использовать, потому что они пропускают некоторые части. Например, я - абстрактная коробка с поддержкой GPS - я знаю, как проверить свое положение на карте:

abstract class GpsBox implements Package {
  @Override
  public abstract String address();
  protected Coordinates whereAmI() {
    // connect to GPS and return my current position
  }
}

Этот класс, если он унаследован / расширен другим классом, может быть очень полезным. Но само по себе - это бесполезно, так как не может иметь объектов. Абстрактные классы могут быть элементами построения конечных классов.

Финальный класс - это группа законченных объектов, которые можно использовать, но нельзя изменить. Они точно знают, как работать и что делать. Например, я ящик, который всегда идет по адресу, указанному при его создании:

final class DirectBox implements Package {
  private final String to;
  public DirectBox(String addr) {
    this.to = addr;
  }
  @Override
  public String address() {
    return this.to;
  }
}

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

Опять же, сравнение интерфейсов с абстрактными классами не является правильным.


9

Вкратце различия следующие:

Синтаксические различия между интерфейсом и абстрактным классом :

  1. Методы и члены абстрактного класса могут иметь любую видимость. Все методы интерфейса должны быть публичными . // больше не выполняется в Java 9
  2. Конкретный детский класс абстрактного класса должен определять все абстрактные методы. Абстрактный класс ребенок может иметь абстрактные методы. Интерфейс расширяет другую потребность интерфейса не обеспечивает реализацию по умолчанию для методов , унаследованных от родительского интерфейса.
  3. Дочерний класс может расширять только один класс. Интерфейс может расширять несколько интерфейсов. Класс может реализовывать несколько интерфейсов.
  4. Дочерний класс может определять абстрактные методы с такой же или менее ограниченной видимостью, тогда как класс, реализующий интерфейс, должен определять все методы интерфейса как общедоступные.
  5. Абстрактные классы могут иметь конструкторы, но не интерфейсы .
  6. Интерфейсы из Java 9 имеют частные статические методы.

В интерфейсах сейчас:

public static- поддерживается
public abstract- поддерживается
public default- поддерживается
private static- поддерживается
private abstract- ошибка
private defaultкомпиляции
private- ошибка компиляции - поддерживается


8

Разница лишь в том, что один может участвовать в множественном наследовании, а другой - нет.

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

Интерфейсы были введены в Java из-за проблемы с множественным наследованием алмазов, и именно это они и намерены делать.

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

См. Почему Java допускает статические конечные переменные в интерфейсах, когда они предназначены только для контрактов? ,


1
Хотя это важное различие, это не единственное отличие.
Говинд Пармар,

7

Интерфейс: поверните (поверните налево, поверните направо)

Абстрактный класс: Колесо.

Класс: рулевое колесо, происходит от колеса, выставляет интерфейс поворота

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


6

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

Следующие примеры демонстрируют это.

Абстрактный класс в Java:

abstract class animals
{
    // They all love to eat. So let's implement them for everybody
    void eat()
    {
        System.out.println("Eating...");
    }
    // The make different sounds. They will provide their own implementation.
    abstract void sound();
}

class dog extends animals
{
    void sound()
    {
        System.out.println("Woof Woof");
    }
}

class cat extends animals
{
    void sound()
    {
        System.out.println("Meoww");
    }
}

Ниже приведена реализация интерфейса в Java:

interface Shape
{
    void display();
    double area();
}

class Rectangle implements Shape 
{
    int length, width;
    Rectangle(int length, int width)
    {
        this.length = length;
        this.width = width;
    }
    @Override
    public void display() 
    {
        System.out.println("****\n* *\n* *\n****"); 
    }
    @Override
    public double area() 
    {
        return (double)(length*width);
    }
} 

class Circle implements Shape 
{
    double pi = 3.14;
    int radius;
    Circle(int radius)
    {
        this.radius = radius;
    }
    @Override
    public void display() 
    {
        System.out.println("O"); // :P
    }
    @Override
    public double area() 
    { 
        return (double)((pi*radius*radius)/2);
    }
}

Несколько важных ключевых моментов в двух словах:

  1. Переменные, объявленные в интерфейсе Java, по умолчанию являются окончательными. Абстрактные классы могут иметь не конечные переменные.

  2. Переменные, объявленные в интерфейсе Java, по умолчанию являются статическими. Абстрактные классы могут иметь нестатические переменные.

  3. Члены интерфейса Java являются общедоступными по умолчанию. Абстрактный класс Java может иметь обычные разновидности членов класса, такие как private, protected и т. Д.


4

Многие младшие разработчики ошибочно считают интерфейсы, абстрактные и конкретные классы незначительными вариациями одного и того же и выбирают один из них исключительно по техническим причинам: нужно ли множественное наследование? Нужно ли какое-то место, чтобы поставить общие методы? Нужно ли беспокоиться о чем-то другом, кроме как о конкретном занятии? Это неправильно, и в этих вопросах скрыта главная проблема: «Я» . Когда вы пишете код для себя, вы редко думаете о других настоящих или будущих разработчиках, работающих над вашим кодом или над ним.

Интерфейсы и абстрактные классы, хотя и кажутся с технической точки зрения схожими, имеют совершенно разные значения и цели.

Резюме

  1. Интерфейс определяет контракт, который некоторая реализация выполнит для вас .

  2. Абстрактный класс обеспечивает поведение по умолчанию, которое ваша реализация может использовать повторно.

Альтернативное резюме

  1. Интерфейс для определения публичных API
  2. Абстрактный класс предназначен для внутреннего использования и для определения SPI

О важности сокрытия деталей реализации

Конкретный класс выполняет реальную работу очень специфическим способом. Например, оператор ArrayListиспользует непрерывную область памяти для компактного хранения списка объектов, который предлагает быстрый произвольный доступ, итерации и изменения на месте, но ужасен при вставках, удалениях и иногда даже добавлениях; между темLinkedList использует двойные узлы для хранения списка объектов, который вместо этого предлагает быструю итерацию, изменения на месте и вставку / удаление / добавление, но ужасен при произвольном доступе. Эти два типа списков оптимизированы для разных вариантов использования, и очень важно, как вы собираетесь их использовать. Когда вы пытаетесь выжать производительность из списка, с которым интенсивно взаимодействуете, и когда выбор типа списка зависит от вас, вы должны тщательно выбрать, какой экземпляр вы создаете.

С другой стороны, пользователям высокого уровня списка на самом деле все равно, как он на самом деле реализован, и они должны быть изолированы от этих деталей. Давайте представим, что Java не предоставляла Listинтерфейс, а имела только конкретный Listкласс, который на самом деле LinkedListи сейчас. Все Java-разработчики приспособили бы свой код к деталям реализации: избегайте произвольного доступа, добавьте кеш для ускорения доступа или просто переопределите ArrayListего самостоятельно, хотя это было бы несовместимо со всем другим кодом, который фактически работает сList только с. Это было бы ужасно ... Но теперь представьте, что мастера Java на самом деле понимают, что связанный список ужасен для большинства реальных случаев использования, и решили переключиться на список массивов только для своих целей.Listкласс доступен. Это повлияет на производительность каждой Java-программы в мире, и люди не будут этому рады. И главный виновник в том, что детали реализации были доступны, и разработчики предположили, что эти детали являются постоянным контрактом, на который они могут положиться. Вот почему важно скрывать детали реализации и определять только абстрактный контракт. Это цель интерфейса: определить, какие входные данные принимает метод и какой ожидаемый результат, не подвергая всех смелости, которая побудит программистов настроить свой код, чтобы соответствовать внутренним деталям, которые могут измениться при любом будущем обновлении ,

Абстрактный класс находится посередине между интерфейсами и конкретными классами. Предполагается, что реализации помогают использовать общий или скучный код. Например, AbstractCollectionпредоставляет базовые реализации для isEmptyоснованного на размере 0, containsкак итерацию и сравнение, addAllкак повторение add, и так далее. Это позволяет реализациям сосредоточиться на важнейших частях, которые различают их: как на самом деле хранить и извлекать данные.

API против SPI

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

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

Разница между API и SPI невелика, но важна: для API основное внимание уделяется тому, кто его использует , а для SPI - тому, кто его реализует .

Добавить методы в API легко, все существующие пользователи API все равно будут компилировать. Добавить методы в SPI сложно, поскольку каждый поставщик услуг (конкретная реализация) должен будет реализовать новые методы. Если для определения SPI используются интерфейсы, поставщик должен будет выпускать новую версию при каждом изменении контракта SPI. Если вместо этого используются абстрактные классы, новые методы могут быть определены либо в терминах существующих абстрактных методов, либо в виде пустых throw not implemented exceptionзаглушек, что по крайней мере позволит более старой версии реализации службы по-прежнему компилироваться и запускаться.

Замечание о Java 8 и методах по умолчанию

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

Какой использовать?

  1. Предполагается, что эта вещь будет публично использоваться другими частями кода или другим внешним кодом? Добавьте интерфейс, чтобы скрыть детали реализации от публичного абстрактного контракта, который является общим поведением вещи.
  2. Является ли , что то , что предполагается иметь несколько реализаций с большим количеством коды в общем? Сделайте и интерфейс и абстрактную, неполную реализацию.
  3. Будет ли когда-нибудь только одна реализация, и никто другой не будет ее использовать? Просто сделайте это конкретным классом.
    1. «когда-либо» - это долгое время, вы можете быть осторожны и все равно добавить интерфейс поверх него.

Следствие: обратное часто делается неправильно: при использовании вещи всегда старайтесь использовать самый универсальный класс / интерфейс, который вам действительно нужен. Другими словами, не объявляйте ваши переменные как ArrayList theList = new ArrayList(), если только у вас на самом деле нет сильной зависимости от того, что он является списком массивов , и никакой другой тип списка не подрезал бы его для вас. Используйте List theList = new ArrayListвместо этого, или даже Collection theCollection = new ArrayListесли факт, что это список, а не какой-либо другой тип коллекции, на самом деле не имеет значения.


4

На самом деле это не ответ на первоначальный вопрос, но как только вы получите ответ на различие между ними, вы введете дилемму «когда использовать каждый»: когда использовать интерфейсы или абстрактные классы? Когда использовать оба?

Я ограничил знание ООП, но видение интерфейсов как эквивалента прилагательного в грамматике до сих пор работало для меня (поправьте меня, если этот метод фальшивый!). Например, имена интерфейсов похожи на атрибуты или возможности, которые вы можете дать классу, и у класса может быть много из них: ISerializable, ICountable, IList, ICacheable, IHappy, ...


3

Наследование используется для двух целей:

  • Позволить объекту рассматривать элементы данных родительского типа и реализации методов как свои собственные.

  • Разрешить использование ссылки на объекты одного типа кодом, который ожидает ссылку на объект супертипа.

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

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

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


3

Ключевые моменты:

  • Абстрактный класс может иметь свойства, поля данных, методы (полные / неполные) и то, и другое.
  • Если метод или Свойства задаются в абстрактном ключевом слове, которое должно переопределяться в производном классе (его работа как тесно связанная функциональность)
  • Если вы определяете абстрактное ключевое слово для метода или свойств в абстрактном классе, вы не можете определить тело метода и получить / установить значение для свойств, которые должны переопределяться в производном классе.
  • Абстрактный класс не поддерживает множественное наследование.
  • Абстрактный класс содержит конструкторы.
  • Абстрактный класс может содержать модификаторы доступа для подпрограмм, функций, свойств.
  • Только полный член абстрактного класса может быть статическим.
  • Интерфейс может наследовать только от другого интерфейса и не может наследовать от абстрактного класса, тогда как абстрактный класс может наследовать от другого абстрактного класса или другого интерфейса.

Преимущество:

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

подробности смотрите здесь ... http://pradeepatkari.wordpress.com/2014/11/20/interface-and-abstract-class-in-c-oops/


3

Кратчайший способ подвести итог - это interface:

  1. Полностью абстрактные, кроме defaultи staticметодов; хотя у него есть определения (сигнатуры методов + реализации) для defaultи staticметодов, у него есть только объявления (сигнатуры методов) для других методов.
  2. Подчиняется более слабым правилам, чем классы (класс может реализовывать несколько interfaces и interfaceможет наследовать от нескольких interfaces). Все переменные неявно постоянны, независимо от того, указаны они public static finalили нет. Все члены неявно public, независимо от того, указаны ли они как таковые или нет.
  3. Обычно используется как гарантия того, что реализующий класс будет иметь указанные функции и / или будет совместим с любым другим классом, который реализует тот же интерфейс.

Между тем, abstractкласс это:

  1. Везде от полностью абстрактного до полностью реализованного, с тенденцией иметь один или несколько abstractметодов. Может содержать как объявления, так и определения, причем объявления помечаются как abstract.
  2. Полноценный класс и подчиняется правилам, которые управляют другими классами (может наследоваться только от одного класса), при условии, что он не может быть создан (поскольку нет гарантии, что он полностью реализован). Может иметь непостоянные переменные-члены. Можно осуществлять контроль доступа членов, ограничивая пользователь , как protected, privateили частный пакет (не указан).
  3. Обычно используется либо для предоставления столько реализации, сколько может совместно использовать несколько подклассов, либо для предоставления столько реализации, сколько может предоставить программист.

Или, если мы хотим свести все это к одному предложению: An interface- это то, что имеет реализующий класс , но abstractкласс - это то, что подкласс является .


3

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


3

Чтобы дать простой, но ясный ответ, это помогает установить контекст: вы используете оба, когда вы не хотите предоставлять полные реализации.

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


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

Как я уже сказал, это должно было стать «простым, но четким ответом» для кого-то на этапе изучения разницы. Для кого-то подобного это не имеет смысла знать об такого рода исключениях, это только очень сбивает с толку.
user3775501

3

Различия между абстрактным классом и интерфейсом от имени реальной реализации.

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

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

Связь между двумя внешними объектами (сторонняя интеграция в нашем приложении) осуществляется через интерфейс здесь интерфейс работает как контракт.

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

Пример абстрактного класса:

 public abstract class DesireCar
  {

 //It is an abstract method that defines the prototype.
     public abstract void Color();

  // It is a default implementation of a Wheel method as all the desire cars have the same no. of wheels.   
 // and hence no need to define this in all the sub classes in this way it saves the code duplicasy     

  public void Wheel() {          

               Console.WriteLine("Car has four wheel");
                }
           }


    **Here is the sub classes:**

     public class DesireCar1 : DesireCar
        {
            public override void Color()
            {
                Console.WriteLine("This is a red color Desire car");
            }
        }

        public class DesireCar2 : DesireCar
        {
            public override void Color()
            {
                Console.WriteLine("This is a red white Desire car");
            }
        }

Пример интерфейса:

  public interface IShape
        {
          // Defines the prototype(template) 
            void Draw();
        }


  // All the sub classes follow the same template but implementation can be different.

    public class Circle : IShape
    {
        public void Draw()
        {
            Console.WriteLine("This is a Circle");
        }
    }

    public class Rectangle : IShape
    {
        public void Draw()
        {
            Console.WriteLine("This is a Rectangle");
        }
    }

3

Вы можете найти четкую разницу между интерфейсом и абстрактным классом.

Интерфейс

  • Интерфейс содержит только абстрактные методы.
  • Заставить пользователей реализовывать все методы при реализации интерфейса.
  • Содержит только конечные и статические переменные.
  • Объявите, используя ключевое слово интерфейса.
  • Все методы интерфейса должны быть определены как публичные.
  • Интерфейс может расширяться или класс может реализовывать несколько других интерфейсов.

Абстрактный класс

  • Абстрактный класс содержит абстрактные и неабстрактные методы.

  • Не заставляет пользователей реализовывать все методы при наследовании абстрактного класса.

  • Содержит все виды переменных, включая примитивные и не примитивные

  • Объявите, используя абстрактное ключевое слово.

  • Методы и члены абстрактного класса могут быть определены с любой видимостью.

  • Дочерний класс может расширять только один класс (абстрактный или конкретный).


2

Абстрактный класс - это класс, объект которого не может быть создан, или класс, который не может быть создан. Абстрактный метод делает класс абстрактным. Абстрактный класс должен быть унаследован, чтобы переопределить методы, объявленные в абстрактном классе. Нет ограничений на спецификаторы доступа. Абстрактный класс может содержать конструктор и другие конкретные (не abstarct методы) методы, но интерфейс не может иметь.

Интерфейс является планом / шаблоном методов (например, дом на бумаге предоставляется (интерфейсный дом), и различные архитекторы будут использовать свои идеи для его создания (классы архитекторов, реализующих интерфейс дома). Это коллекция абстрактные методы, методы по умолчанию, статические методы, конечные переменные и вложенные классы. Все члены будут либо финальными, либо открытыми, спецификаторы защищенного и закрытого доступа не допускаются. Создание объекта не допускается. Необходимо создать класс, чтобы использовать реализации интерфейса, а также для переопределения абстрактного метода, объявленного в интерфейсе. Интерфейс является хорошим примером слабой связи (динамический полиморфизм / динамическое связывание). Интерфейс реализует полиморфизм и абстракцию. Он говорит, что делать, но как делать, определяется реализующий класс. Например.Это автомобильная компания, и она хочет, чтобы некоторые функции были одинаковыми для всех автомобилей, которые она выпускает, поэтому компания будет производить интерфейсное транспортное средство, которое будет иметь эти функции и различные классы автомобилей (такие как Maruti Suzkhi, Maruti 800) будут переопределены эти функции (функции).

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


2

В терминах практичности (JAVA) основное различие между абстрактным классом и интерфейсом состоит в том, что абстрактный класс может содержать состояние. Кроме состояния удержания мы можем выполнять операции покоя и с интерфейсом.


1

В интерфейсе все методы должны быть только определениями, ни один не должен быть реализован.

Но в абстрактном классе должен существовать абстрактный метод только с определением, но другие методы также могут быть в абстрактном классе с реализацией ...


1

У нас есть различные структурные / синтаксические различия между интерфейсом и абстрактным классом. Еще некоторые отличия

[1] Разница на основе сценария :

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

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

[2] Концептуальная разница :

«Нужно ли нам предоставлять больше абстрактных методов в будущем», если ДА сделает его абстрактным классом, и если НЕТ, то сделает его Интерфейсом.

(Наиболее подходящий и действительный до Java 1.7)


1

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

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

Интерфейс имеет широкий спектр абстракций, а не абстрактный класс. Вы можете увидеть это в передаче аргументов. посмотрите этот пример:

введите описание изображения здесь

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.