Что плохого в использовании категории в NSObject для обеспечения реализации протокола по умолчанию?

Я искал способ использовать дополнительные методы протокола и иметь чистый код. Другими словами:
1: Нет respondsToSelector: вызовов во всем моем коде
2. Должен работать для любой сигнатуры метода, поэтому метод категории в NSObject, выполняющий проверку и вызывающий performSelector:, отсутствует (и у NSInvocation есть проблемы с взаимодействием с ARC)
3: Это solution, 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