为什么协议对超级 class 隐藏方法和属性?
Why is a protocol hiding methods and properties from the super class?
考虑这个 class:CAEmitterLayer
。此 class 响应 属性 name
.
现在我创建了一个名为 MyEmitter
的 CAEmitterLayer
,这个 class 符合我创建的名为 MyProtocol
的协议。
MyEmitter
class 声明是这样的:
HEADER
#import "MyProtocol.h"
@interface MyEmitter : CAEmitterLayer <MyProtocol>
@end
实施
#import "MyEmitter.h"
@implementation MyEmitter
@synthesize internalString = _internalString;
@end
协议就是这样:
@protocol MyProtocol <NSObject>
@property (nonatomic, strong) NSString * internalString;
@end
这就是问题所在。如果我像这样创建一个新的 object
MyEmitter *obj = [[MyEmitter alloc] init];
并尝试使用 name
属性,xcode 抱怨 没有已知的选择器实例方法 'name'
事实上,我无法从 class CAEmitterLayer
访问任何 属性,即使 MyEmitter
是 class 的子class。
我正在尝试这样使用它:
for (id <MyProtocol> node in nodes) {
[node setName:@"ddd"]; // error here
}
显然协议对超级 class 隐藏了一切。为什么会这样,我该如何解决?
注意:我必须将该综合行添加到 class,否则 xcode 不会停止抱怨。
node
的静态类型是id <MyProtocol>
。编译器正确地说此类型未声明 [=12=] 方法。
只需切换到 MyEmitter *
即可。
为了进一步说明其他答案,您会收到一个编译时错误,因为编译器必须按照您告诉它的内容进行工作。
现在,您知道(或至少希望)node
将在 运行 时成为 MyEmitter
的一个实例,但编译器不会,因为您告诉它 node
是一个 id <MyProtocol>
.
如果你能让你的程序达到 运行,那么 [node setName:]
就可以工作,因为 objective-C 在 运行 的时候找到了正确的选择器。
类似地,如果您告诉编译器 node
是 MyEmitter
的一个实例,但在 运行 时它是一个不同的对象 class (由于某个地方的错误else 在你的代码中)然后它会编译但可能在 运行 时间抛出异常。
所以你可以说 -
for (MyEmitter *node in nodes) {
[node setName:@"ddd"];
}
或者,如果您不需要为您的子class做任何特定的事情,您甚至可以说
for (CAEmitterLayer *node in nodes) {
[node setName:@"ddd"];
}
考虑这个 class:CAEmitterLayer
。此 class 响应 属性 name
.
现在我创建了一个名为 MyEmitter
的 CAEmitterLayer
,这个 class 符合我创建的名为 MyProtocol
的协议。
MyEmitter
class 声明是这样的:
HEADER
#import "MyProtocol.h"
@interface MyEmitter : CAEmitterLayer <MyProtocol>
@end
实施
#import "MyEmitter.h"
@implementation MyEmitter
@synthesize internalString = _internalString;
@end
协议就是这样:
@protocol MyProtocol <NSObject>
@property (nonatomic, strong) NSString * internalString;
@end
这就是问题所在。如果我像这样创建一个新的 object
MyEmitter *obj = [[MyEmitter alloc] init];
并尝试使用 name
属性,xcode 抱怨 没有已知的选择器实例方法 'name'
事实上,我无法从 class CAEmitterLayer
访问任何 属性,即使 MyEmitter
是 class 的子class。
我正在尝试这样使用它:
for (id <MyProtocol> node in nodes) {
[node setName:@"ddd"]; // error here
}
显然协议对超级 class 隐藏了一切。为什么会这样,我该如何解决?
注意:我必须将该综合行添加到 class,否则 xcode 不会停止抱怨。
node
的静态类型是id <MyProtocol>
。编译器正确地说此类型未声明 [=12=] 方法。
只需切换到 MyEmitter *
即可。
为了进一步说明其他答案,您会收到一个编译时错误,因为编译器必须按照您告诉它的内容进行工作。
现在,您知道(或至少希望)node
将在 运行 时成为 MyEmitter
的一个实例,但编译器不会,因为您告诉它 node
是一个 id <MyProtocol>
.
如果你能让你的程序达到 运行,那么 [node setName:]
就可以工作,因为 objective-C 在 运行 的时候找到了正确的选择器。
类似地,如果您告诉编译器 node
是 MyEmitter
的一个实例,但在 运行 时它是一个不同的对象 class (由于某个地方的错误else 在你的代码中)然后它会编译但可能在 运行 时间抛出异常。
所以你可以说 -
for (MyEmitter *node in nodes) {
[node setName:@"ddd"];
}
或者,如果您不需要为您的子class做任何特定的事情,您甚至可以说
for (CAEmitterLayer *node in nodes) {
[node setName:@"ddd"];
}