Какво не е наред с използването на категория в NSObject за осигуряване на изпълнение на протокол по подразбиране?

Търсих начин да използвам незадължителни протоколни методи и да имам чист код. С други думи:
1: Няма respondsToSelector: извиквания в целия ми код
2. Трябва да работи за всеки подпис на метод, така че метод на категория на NSObject, който прави проверката и извиква performSelector:, не работи (и NSInvocation има проблеми със сътрудничеството с ARC)
3: Това решение, IMO, се преструва, че е универсално, но има всички недостатъци на 1

В крайна сметка стигнах до тази идея:

@protocol MyProtocol <NSObject>
@optional
-(void)optionalMethod;
@end

@interface ClassA : NSObject <MyProtocol>
@end

@implementation ClassA

-(void)optionalMethod{
     NSLog(@"ClassA implements optionalMethod");
}

@end

@interface ClassB : NSObject <MyProtocol>
@end

@implementation ClassB
//classB does not implement optionalMethod
@end

@interface NSObject (DefaultMyProtocolImplementation)
-(void)optionalMethod;
@end

@implementation NSObject (DefaultMyProtocolImplementation)
-(void)optionalMethod{
     NSLog(@"%@ does not implement optionalMethod", NSStringFromClass([self class]));
}
@end

Изглежда, че работи, т.е.:

...
ClassA *objA = [[ClassA alloc] init];
ClassB *objB = [[ClassB alloc] init];

[objA optionalMethod]; //prints "ClassA implements optionalMethod"
[objB optionalMethod]; //prints "ClassB does not implement optionalMethod"

Въпреки че на много места онлайн се обсъжда този проблем, аз не попаднах на това решение, което ме кара да мисля, че има нещо нередно с него -- някакъв основен случай, при който ще се провали или ще бъде непредсказуем.

Трябва ли просто да го направя или притесненията ми са основателни?


person executor21    schedule 12.10.2013    source източник
comment
Единственото нещо, за което наистина мога да се сетя досега, е, че няма да получите предупреждение от компилатора за [objectWhichDoesNotDeclareConformanceToTheProtocol theOptionalProtocolMethod]; Това всъщност е начинът, по който първоначално са били внедрени незадължителните протоколни методи: Неформален протокол в ObjC Другото нещо е, че методите, които вие добавяте към класовете на рамката, в идеалния случай трябва да имат префикс, за да се избегнат сблъсъци.   -  person jscs    schedule 12.10.2013


Отговори (1)


Методите, добавени към съществуващи системни класове, трябва да имат префикс по някакъв начин. т.е. exec_myMethod или exec_doSomethingToThis:. Така че вашето решение е в нарушение на това.

Освен това, това също означава, че даден клас не може да се откаже от каквото и да е поведението на метода @optional по подразбиране (което по същество е нищо, защото вашето внедряване по подразбиране наистина трябва да бъде без операция).

Така че, не, като цяло, няма нещо ужасно нередно в предоставянето на внедряване по подразбиране извън нарушението на правилото трябва да добави префикс за добавяне на методи чрез категория към съществуващи класове. Но това не е трудно правило.

Другият недостатък е, че замърсявате пространството от имена на метода. Това ще бъде недостатък по време на разработката, тъй като Xcode ще кодира всички методи, лесно избегнати, като просто не излагате декларациите (които не е необходимо да бъдат излагани). По време на изпълнение това означава, че respondsToSelector: не е полезен за тези методи, но това е някак по замисъл.

Все пак... мирише на обонятелния център на стария код.

person bbum    schedule 15.10.2013