Какова цель абстрактных классов? - PullRequest
14 голосов
/ 18 февраля 2010

Я пытаюсь выучить ООП на PHP, и у меня возникли некоторые сомнения по поводу интерфейсов и абстрактных классов. Они оба не содержат реализаций, только определения, и должны быть реализованы через их подклассы. Какая часть абстрактных классов четко отличает их от интерфейсов? Кроме того, из-за их очевидного сходства, по каким причинам я должен решить использовать один над другим?

Ответы [ 7 ]

8 голосов
/ 18 февраля 2010

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

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

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

4 голосов
/ 18 февраля 2010

Класс abstract образует отношение is-a между собой и подклассом, в то время как interface создает follow- отношения. Как таковые, абстрактные классы намного более конкретны, чем интерфейсы, и они могут также содержать конкретные реализации (например, методы шаблона ), в то время как интерфейс определяет договорный набор методов, которым должен следовать реализующий класс. Это намного более высокий уровень абстракции, поскольку реализующий класс не обязательно должен принадлежать абстрактному классу. Используйте его для стандартизации вашего API.

Похожие вопросы: https://stackoverflow.com/search?q=abstract+vs+interface

3 голосов
/ 18 февраля 2010

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

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

3 голосов
/ 18 февраля 2010

Они оба не содержат реализаций.

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

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

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

2 голосов
/ 10 февраля 2016

Основное различие между абстрактным классом и интерфейсом состоит в том, что интерфейс определяет общее поведение, где абстрактный класс является базовым классом для наследования.Другими словами, абстрактный класс определяет некоторый основной набор методов и свойств, которые могут совместно использовать подклассы.Рассмотрим класс, который определяет лицензию.Все лицензии имеют идентификационный номер определенного типа и выдаются какому-либо лицу или группе.Класс лицензии может быть расширен классом водительских прав, классом велосипедов и лицензией на охоту и т. Д.Основная причина, по которой можно сделать класс License абстрактным, состоит в том, что он определяет абстрактное представление о лицензии.Нет такой вещи как лицензия, поэтому, объявляя абстрактный класс, он не может быть создан.
Интерфейс, с другой стороны, вообще не определяет объект.Он определяет сигнатуры методов.Любой неабстрактный класс, который реализует интерфейс, должен обеспечивать реализацию для всех методов в интерфейсе.Преимущество здесь заключается в том, что метод обеспечивает общий интерфейс для различных типов объектов, например, CompareTo () выглядит одинаково при использовании со строками или любым другим объектом.

0 голосов
/ 18 февраля 2010

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

A. Модули высокого уровня не должны зависеть от модулей низкого уровня. Оба должны зависеть от абстракций.

B. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций. "

Таким образом, если вы определяете функции и методы, вместо подсказки типа для классов, вы просто намекаете на интерфейсы.

Вот пример. Допустим, вы определяете интерфейсы для входных и выходных потоков следующим образом:

interface OutputStream{
  write($string); // Writes a string to the output.
  close(); // Closes the output stream.
}

interface InputStream{
  read($length); // Reads at most $length characters.
  eof(); // TRUE, if the input stream is empty.
}

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

// 50 is just chosen randomly.
function copy(InputStream $input, OutputStream $output){
  while(!$input->eof()){
    $output->write($input->read(50));}}

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

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

Опять пример. Допустим, вы хотите иметь выходные потоки. Вам нужен метод write($s), который записывает строку в вывод, и вам нужен метод writeLine($s), который записывает строку и дополнительный символ новой строки в вывод. Тогда это будет уместно:

abstract class AbstractOutputStream{
  public function writeLine($s){
    $this->write($s."\n");}}

Конкретные выходные потоки теперь могут наследоваться от абстрактного выходного потока, реализовать только write и получить writeLine бесплатно!

0 голосов
/ 18 февраля 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...