Большой вопрос. Я отошлю Вас к Josh Bloch в Эффективном Java, который пишет (объект 16), почему предпочесть использование интерфейсов по абстрактным классам. Между прочим, если у Вас нет этой книги, я настоятельно рекомендую его! Вот сводка того, что он говорит:
Что относительно преимущества абстрактных классов, обеспечивающих базовое внедрение? Можно предоставить абстрактному скелетному классу реализации каждый интерфейс. Это комбинирует достоинства и интерфейсов и абстрактных классов. Скелетные реализации оказывают помощь реализации, не налагая серьезные ограничения, которые вызывают абстрактные классы, когда они служат определениями типа. Например, эти Платформа Наборов определяет интерфейсы использования типа и предоставляет скелетную реализацию каждому.
Приведу вам пример. У меня есть несколько классов ObjC, которые взаимодействуют с Flickr API. Один, называемый FKAccount
, может выполнять множество действий, связанных с учетной записью пользователя Flickr, включая загрузку фотографий пользователя, получение их списка контактов и т. Д.
Класс FKAccount
определяет делегата протокол FKAccountDelegate
. Этот протокол определяет ряд методов обратного вызова, которые FKAccount
будет вызывать для своего делегата в зависимости от успеха или неудачи различных сетевых операций с Flickr. Не каждое приложение, использующее FKAccount
, будет интересоваться каждой операцией Flickr, которую может выполнить FKAccount
.
Если бы требовалось, чтобы каждый класс, претендующий на реализацию протокола FKAccountDelegate
, реализовывал каждый метод, вы бы получили множество методов-заглушек (FWIW, существует 41 метод, определенный в FKAccountDelegate
). Когда эти методы объявлены в протоколе @optional
, делегату нужно реализовать только те обратные вызовы, которые он хочет получить.
Класс FKAccount
проверяет, отвечает ли его делегат на ] @optional
методы в протоколе:
if([self.delegate respondsToSelector: @selector(accountDidDownloadContacts:)]) {
[self.delegate accountDidDownloadContacts: self];
}