views:

490

answers:

3

I'd like an instance variable object to adopt a protocol.

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

For example I'd like my Layer object to adopt the <CocosNodeOpacity> so that I can get the methods

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

for free. The syntax shown above is invalid. Is it possible to achieve this without creating a new implementation file and creating a custom object? Thanks.

+2  A: 

Hi Stu,

A protocol in Objective-C is similar to an interface in Java. The protocol defines a set of functions and acts as a contract. It's like saying "I guarantee that whatever this object is, it has these methods."

You're pretty close on the syntax in your first code block. It would actually look something like this:

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

However, that doesn't save you from having to define the methods for opacity in your Layer class. Using the protocol, you've established that your class will have those functions, but you haven't actually provided them. You'll still need to write the code for them.

I think what you're looking for is an Objective-C category. A category provides a way to extend the functionality of any class by adding methods to it at runtime. They're possible because Objective-C is a completely dynamic language. If you aren't the author of the Layer class and can't easily add the opacity methods to it, a category is the way to go. In some cases, categories are extremely useful - you can add methods to built-in classes, like NSString and NSColor, without having the existing class source.

There's plenty of documentation for categories here on stack overflow. The apple docs are also very good. Here's an article to get you started:

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

Ben Gotow
+5  A: 

If these are all code you created, the best way to do this is probably to make the Layer class itself adopt the protocol, rather than the variable.

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

A key benefit to this approach is that the compiler will check whether you've implemented all required methods in the protocol at compile time, which is generally what you want. Adding the methods in same place as the rest of the standard class implementation is easier to understand (no hunting to find where the magical code came from) and less fragile than using categories (adding the same method via different categories can result in undefined behavior). As a general rule, I only use categories when I have to, such as adding methods to (closed-source) third-party code.

If you don't control the source of Layer, you may have to use this instead when you declare your ivar:

Layer<CocosNodeOpacity> *content;

Note that adopting a protocol allows you to statically type variables with a class type and get compile warnings if the methods aren't present. However, you don't get the methods "for free", since you still have to implement them. Still, judicious use of protocols and static typing can make your code more robust and "fail-fast" than using id as the type for everything. You are to be commended for not just taking the easy way out. :-)

For some details about protocols (including required and optional methods) see this SO answer.

Quinn Taylor
A: 

hello all what's a word "USING" in @protocol declaration

@protocol name USING @end

thank for all contributter

tayebi mohammed