2015-03-15 2 views
0

Рассмотрите этот класс: CAEmitterLayer. Этот класс отвечает на свойство name.Почему методы и свойства протокола скрываются от суперкласса?

Теперь я создал CAEmitterLayer под названием MyEmitter, и этот класс соответствует протоколу, который я создал под названием MyProtocol.

MyEmitter объявление класса, как это:

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 

В этом проблема. Если я создаю новый объект, как этот

MyEmitter *obj = [[MyEmitter alloc] init]; 

и попытаться использовать name свойство, Xcode жалуется не известный метод экземпляра для селекторного «имя»

На самом деле я не могу получить доступ к любой собственности от класс CAEmitterLayer даже MyEmitter является подклассом этого класса.

Я пытаюсь использовать его как это:

for (id <MyProtocol> node in nodes) { 
    [node setName:@"ddd"]; // error here 
    } 

Видимо протокол скрывает все от суперкласса. Почему это и как я могу решить?

ПРИМЕЧАНИЕ. Мне пришлось добавить эту синтезирующую строку в класс, иначе xcode не перестанет жаловаться.

+0

Покажите, как вы пытаетесь использовать его, на самом деле он использует 'obj' из вашей кодовой строки? Можете ли вы получить доступ к 'internalString' без ошибок? И да, свойства протокола всегда должны быть синтезированы (или переопределены). – Wain

+0

добавлен в вопрос .... да, я могу получить доступ к internalString. – SpaceDog

+0

Я не могу получить доступ к любому свойству CAEmitterLayer ... – SpaceDog

ответ

4

Статический тип node - id <MyProtocol>. Компилятор справедливо говорит, что этот тип не объявляет метод setName:.

Просто переключитесь на MyEmitter *, и он должен работать.

+0

, так что это правильное поведение? благодаря!!! – SpaceDog

+1

Почему, конечно. Это то, что касается безопасности статического типа. –

2

Чтобы развернуть другой ответ, вы получаете сообщение об ошибке , потому что компилятор должен работать из того, что вы ему сказали.

Теперь вы знаете (или по крайней мере, надежда), что node будет экземпляром MyEmitter во время выполнения, но компилятор не потому, что вы сказали, что это node является id <MyProtocol>.

Если бы вы могли запустить вашу программу в любом случае, тогда [node setName:] будет работать, потому что цель-C находит правильный селектор во время выполнения.

Аналогично, если вы сказали компилятору, что node был экземпляром MyEmitter, но во время выполнения это был другой класс объектов (из-за ошибки где-то еще в вашем коде), тогда он скомпилировал бы, но потенциально выдавал исключение во время выполнения ,

Таким образом, можно сказать, -

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

Или, если вам не нужно делать ничего, что является специфичным для подкласса можно даже сказать,

for (CAEmitterLayer *node in nodes) { 
    [node setName:@"ddd"]; 
} 
Смежные вопросы