Цель-C: Протоколы - PullRequest
       21

Цель-C: Протоколы

2 голосов
/ 24 июня 2009

Я бы хотел, чтобы объект переменной экземпляра принял протокол.

@interface GameScene : Scene <AVAudioPlayerDelegate> {
@private
    Layer *content <CocosNodeOpacity>;
}

Например, я бы хотел, чтобы мой объект Layer принял <CocosNodeOpacity>, чтобы я мог получить методы

-(GLubyte) opacity;    //and
-(void) setOpacity: (GLubyte) opacity;

бесплатно. Синтаксис, показанный выше, недействителен. Возможно ли достичь этого без создания нового файла реализации и создания пользовательского объекта? Спасибо.

Ответы [ 2 ]

5 голосов
/ 24 июня 2009

Если это весь код, который вы создали, то лучший способ сделать это, вероятно, заставить сам класс Layer принять протокол, а не переменную.

@interface Layer : NSObject <CocosNodeOpacity> { ... }

Ключевым преимуществом этого подхода является то, что компилятор проверит, реализовали ли вы все необходимые методы в протоколе во время компиляции, что, как правило, то, что вам нужно. Добавление методов в том же месте, что и в остальной части реализации стандартного класса, проще для понимания (нет необходимости искать источник магического кода) и менее хрупко, чем использование категорий (добавление одного и того же метода через разные категории может привести к неопределенному поведению) , Как правило, я использую категории только тогда, когда у меня есть , например, добавление методов к стороннему коду (с закрытым исходным кодом).

Если вы не контролируете источник Layer, вам, возможно, придется использовать это вместо того, чтобы объявить свой ивар:

Layer<CocosNodeOpacity> *content;

Обратите внимание, что принятие протокола позволяет вам статически печатать переменные с типом класса и получать предупреждения компиляции, если методы отсутствуют. Тем не менее, вы не получаете методы «бесплатно», так как вам все равно придется их реализовывать. Тем не менее, разумное использование протоколов и статическая типизация могут сделать ваш код более надежным и «отказоустойчивым», чем использование id в качестве типа для всего. Вы должны быть благодарны за то, что вы не просто взяли легкий путь. : -)

Подробнее о протоколах (включая обязательные и необязательные методы) см. этот ответ SO .

2 голосов
/ 24 июня 2009

Протокол в Objective-C похож на интерфейс в Java. Протокол определяет набор функций и действует как контракт. Это все равно что сказать: «Я гарантирую, что какой бы ни был этот объект, у него есть эти методы».

Вы довольно близки к синтаксису в вашем первом блоке кода. На самом деле это будет выглядеть примерно так:

@interface GameScene : Scene <AVAudioPlayerDelegate> {
@private
    Layer<CocosNodeOpacity> * content;
}

Однако это не избавляет вас от необходимости определять методы непрозрачности в вашем классе Layer. Используя протокол, вы установили, что ваш класс будет иметь эти функции, но на самом деле вы их не предоставили. Вам все еще нужно написать код для них.

Я думаю, вы ищете категорию Objective-C. Категория предоставляет способ расширить функциональность любого класса, добавляя к нему методы во время выполнения. Они возможны, потому что Objective-C - полностью динамический язык. Если вы не являетесь автором класса Layer и не можете легко добавить к нему методы непрозрачности, вам следует выбрать категорию. В некоторых случаях категории чрезвычайно полезны - вы можете добавлять методы во встроенные классы, такие как NSString и NSColor, без наличия источника исходного класса.

Здесь есть много документации для категорий по переполнению стека. Документы по яблоку тоже очень хорошие. Вот статья, с которой можно начать:

http://macdevelopertips.com/objective-c/objective-c-categories.html

...