Категории против неформальных протоколов - PullRequest
4 голосов
/ 02 февраля 2010

Мне кажется, я понял разницу между (формальными) протоколами и категориями. Теперь, если я правильно понял, неофициальные протоколы должны быть категориями (обычно определяемыми в NSObject), которые используются для определенных целей (возможно, чтобы дать возможность реализовать только часть методов, перечисленных в нем, в отличие от формальных протоколов). Я должен быть уверен в этом: Может ли кто-нибудь подтвердить, что неофициальный протокол просто является категорией (или объяснить различия)? Спасибо.

Ответы [ 4 ]

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

Категория - это расширение функциональности класса - это реализация некоторых методов:

@interface NSObject (MyCategory)
  - (void)doSomething;
@end

...

@implementation NSObject (MyCategory)
  - (void)doSomething {
    // do something...
  }
@end

Формальный протокол - это нечто совершенно другое.Если вы знакомы с каким-либо другим объектно-ориентированным языком, то он похож на интерфейс (в Java, C ++, C # и т. Д.).Протокол может быть присоединен к любой реализации класса, например:

@protocol MyProtocol
@required
- (void)doSomething;
@optional
- (void)doSomethingOptional;
@end

...

@interface MyClass : NSObject <MyProtocol> {
}
@end

...

@implementation MyClass
  - (void)doSomething {
    // do something...
  }
@end

Согласно документации, неофициальные протоколы являются категориями класса NSObject (я никогда не использовал этот подход):

@interface NSObject (MyInformalProtocol)
- (void)doSomething;
@end

...

@implementation NSObject (MyInformalProtocol)
  - (void)doSomething {
    // do something...
  }
@end
5 голосов
/ 02 февраля 2010

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

@protocol GLFunkyObjectDelegate
@optional
-(void)funkyObject: (GLFunkyObject *)obj willDoSomething: (GLSomeThing *)thing;
-(void)funkyObject: (GLFunkyObject *)obj didDoSomething: (GLSomeThing *)thing;
@end

@interface GLFunkyObject {
  id <GLFunkyObjectDelegate> delegate;
}
//...
@end
3 голосов
/ 02 февраля 2010

В руководстве Objective-C говорится, что вы правы - неофициальные протоколы обычно являются категориями.

В дополнение к формальным протоколам вы также можете определить неформальный протокол, сгруппировав методы в объявлении категории:

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

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

Протокол - это ТОЛЬКО определение интерфейса.

Категория (против NSObject) является как определением интерфейса, так и реализацией этого интерфейса, который наследуются всеми подклассами (из NSObject), если они не переопределяют методы категории.

Хотя в прошлом Apple предпочитала определять неофициальные протоколы путем создания категорий против NSObject, это не означает, что один является определением другого.

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

...