Можно ли наследовать протоколы и категории Objective-C? - PullRequest
17 голосов
/ 19 сентября 2011

Меня немного смущают некоторые концепции, касающиеся протоколов и категорий Objective-C.

Могут ли протоколы и категории наследоваться подклассами в Objective-C?

Ответы [ 5 ]

31 голосов
/ 19 сентября 2011

Категории - это наборы методов, которые добавляются в класс во время выполнения. Поскольку Objective-C использует динамическое связывание, это означает, что методы, определенные в категории, доступны для класса и всех его подклассов. В частности, селекторы привязаны к методам в той точке, где они вызываются, а не во время компиляции или при первой загрузке программы. Категории добавляются в классы, когда они (категории) загружаются.

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

Сами протоколы могут быть расширены для создания новых протоколов. состоящий из надмножества методов в исходном протоколе. Фактически, так же как большинство классов наследуются от класса NSObject, большинство протоколов расширяют протокол NSObject (имена протоколов и имена классов находятся в разных пространствах имен). Это делается для того, чтобы объекты, объявленные как id<WhateverProtocol>, могли отправлять базовые сообщения, такие как -retain, -release и т. Д., Без генерации предупреждений компилятора.

6 голосов
/ 19 сентября 2011

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

Принимая во внимание, что протокол - это список методов, который требует, чтобы класс, который подтверждает это, реализовал все это (если он не использует тег @optional).Так что нет смысла наследовать его подклассу.

Редактировать:

Для реализации протокола я понял, что не достаточно ясен.Методы протокола, которые были реализованы в его суперклассе , могут * наследоваться , однако я имел в виду, что обычно вам не нужно переопределять метод протокола вашего суперкласса.

4 голосов
/ 19 сентября 2011

Ваш вопрос неясен. Вы можете спросить, наследуют ли подклассы протоколы и категории своего суперкласса. @theAmateurProgrammer ответил на это.

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

@protocol SomeProtocol <NSObject>
...
@end

Это говорит о том, что все, что соответствует <SomeProtocol>, также соответствует <NSObject> (который является протоколом, а также классом). Это позволяет вам вызывать методы, подобные respondsToSelector:, что очень важно для большинства реализаций протокола.

2 голосов
/ 19 сентября 2011

Протоколы похожи на интерфейсы в Java. Итак, класс предоставляет протокол для доступа к нему.

Вы можете «подклассировать» протоколы так же, как в Java вы можете «подклассить» интерфейсы.

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

Это очень полезно, поскольку позволяет избежать создания большой хрупкой иерархии подклассов.

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

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

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

1 голос
/ 11 августа 2014

NSObject соответствует протоколу NSObject

@interface NSObject <NSObject> {
    Class isa  OBJC_ISA_AVAILABILITY;
}

Скажем, у нас есть подкласс NSObject

@interface FTGAnimal : NSObject

@end

@implementation FTGAnimal

@end

Мы можем видеть, что FTGAnimal фактически соответствует протоколу NSObject

if ([FTGAnimal conformsToProtocol:@protocol(NSObject)]) {
        NSLog(@"FTGAnimal conforms to NSObject protocol");
}
...