Проверка того, соответствует ли объект двум отдельным протоколам в Objective-C
В Objective-C, когда вы объявляете переменную экземпляра, вы можете проверить, соответствует ли она протоколу назначения при компиляции так:
id <MyProtocol> variable;
Можно ли проверить, соответствует ли объект, назначенный переменной, двум разным протоколам во время компиляции? Как в:
id <MyProtocol, MyOtherProtocol> variable;
Я знаю, что могу выполнять проверку времени выполнения с помощью conformsToProtocol:
и respondsToSelector
et al (что я делаю до фактического использования объекта для дополнительной безопасности), и я мог бы написать свой собственный метод setter, который выполняет проверку, но я Мне хотелось бы узнать во время компиляции.
Ответы
Ответ 1
Я думаю, что лучше всего использовать свой собственный код:
id <MyProtocol, MyOtherProtocol> variable;
И перед вызовом метода проверьте, отвечает ли переменная на то, что вы хотите вызвать:
if ([variable respondsToSelector:@selector(aMethod:)]) {
[variable aMethod:nil];
}
Поскольку Objective-C является динамическим языком, просто объявление протокола переменных не может гарантировать, что оно соответствует протоколу. В основном он генерирует предупреждения при создании.
Ответ 2
Да, этот синтаксис верен.
Правильный способ проверки соответствия объекта протоколу:
if ([myObj conformsToProtocol:@protocol(MyProtocol)]) {
//conformance!
}
Обратите внимание, что это работает как метод экземпляра, так и метод класса.
Если по какой-то странной причине вы не можете использовать conformsToProtocol:
, вы можете опуститься до уровня времени выполнения:
#import <objc/runtime.h>
Protocol * p = objc_getProtocol("MyProtocol");
if (class_conformsToProtocol([myObj class], p)) {
//conformance!
}
Ответ 3
Вы не всегда проверяете соответствие протокола во время компиляции, потому что объект (неквалифицированный) тип id
всегда является допустимым объектом с точки зрения компиляторов. Например,
id<P1> p1;
id<P2> p2;
id p0;
// compiler warning: assigning to 'id<P1>' from incompatible type 'id<P2>'
p1 = p2;
// no compiler warning
p0 = p2;
p1 = p0;
При этом <P1, P2>
предоставит вам предупреждения в случае, если объект не соответствует обоим протоколам, если это известно во время компиляции:
id<P1> p1;
id<P2> p2;
id<P1, P2> p12;
id<P1, P2> q12;
id p0;
p12 = p1; // warning: assigning to 'id<P1,P2>' from incompatible type 'id<P1>'
p12 = p2; // warning: assigning to 'id<P1,P2>' from incompatible type 'id<P2>'
p12 = q12; // no compiler warning
// no compiler warning
p0 = p1;
p12 = p0;