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

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

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

5 ответов


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

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

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


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

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

Edit:

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


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

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

@protocol SomeProtocol <NSObject>
...
@end

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


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

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

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

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

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

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

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


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");
}