13

在 Objective-C 中,当您声明一个实例变量时,您可以在编译时检查它是否符合分配协议,如下所示:

id <MyProtocol> variable;

是否可以在编译时检查分配给变量的对象是否符合两个单独的协议?如:

id <MyProtocol, MyOtherProtocol> variable;

我知道我可以使用conformsToProtocol:and respondsToSelectoret al 进行运行时检查(在实际使用对象之前我会这样做以增加安全性),并且我可以编写自己的 setter 方法来进行检查,但我想在编译时知道。

4

3 回答 3

55

是的,该语法是正确的。

检查对象是否符合协议的正确方法是这样做:

if ([myObj conformsToProtocol:@protocol(MyProtocol)]) {
  //conformance!
}

请注意,这既可以用作实例方法,也可以用作类方法。

如果由于某些奇怪的原因您不能使用conformsToProtocol:,您可以下拉到运行时级别:

#import <objc/runtime.h>

Protocol * p = objc_getProtocol("MyProtocol");
if (class_conformsToProtocol([myObj class], p)) {
  //conformance!
}
于 2011-01-10T16:58:39.363 回答
13

我认为最好的方法是使用您自己的代码:

id <MyProtocol, MyOtherProtocol> variable;

在调用方法之前,检查变量是否响应您要调用的内容:

if ([variable respondsToSelector:@selector(aMethod:)]) {
    [variable aMethod:nil];
}

由于 Objective-C 是一种动态语言,仅仅声明变量协议并不能保证它符合协议。它主要会在您构建时生成警告。

于 2011-01-10T14:06:17.463 回答
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;
于 2011-01-10T14:02:01.583 回答