为什么协议对超级 class 隐藏方法和属性?

Why is a protocol hiding methods and properties from the super class?

考虑这个 class:CAEmitterLayer。此 class 响应 属性 name.

现在我创建了一个名为 MyEmitterCAEmitterLayer,这个 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 在 运行 的时候找到了正确的选择器。

类似地,如果您告诉编译器 nodeMyEmitter 的一个实例,但在 运行 时它是一个不同的对象 class (由于某个地方的错误else 在你的代码中)然后它会编译但可能在 运行 时间抛出异常。

所以你可以说 -

 for (MyEmitter *node in nodes) {
    [node setName:@"ddd"]; 
 }

或者,如果您不需要为您的子class做任何特定的事情,您甚至可以说

 for (CAEmitterLayer *node in nodes) {
    [node setName:@"ddd"]; 
 }