Question

I have class "Character," which is a subclass of CCSprite. "Character" has only one property, int "extraTag." I am using method getChildByTag:, which returns a CCSprite casted into a CCNode. What I want to do is for it to "cast" it to "Character." I know that casting any class to its subclass is bad practice (and wouldn't work anyway), so I would like to know if it's possible to somehow change the CCSprite to "Character." Function overload doesn't exist in Obj-C, so that's out of the possibilities.

Any help is appreciated; thank you.

PS: If you're wondering why I am subclassing "CCSprite" for one property, it's because I'm using "extraTag" to store when the "CCSprite" is animated. When I call runAction:, it will set "extraTag" to the current action name. I don't want to mess with the existing "tag" property from CCNode, because it's handle by Cocos2D internally for other reasons. If this raises a red flag, let me know; I want to avoid bad practices as much as possible! (:

Was it helpful?

Solution 2

If I understand your goal correctly you wish to add a new property to an existing instance of a class - hence your idea of defining a subclass and trying to "cast" the wrong way. As has be pointed out you cannot do that.

Wrapping an existing instance in another class which has the desired new property would bind your two things - the property and the instance - together, but as an instance of your wrapper class, which I don't think is what you're after. You can use a wrapper to achieve your goal - you define a subclass with both the property and a reference to your existing class, and forward methods to your captured instance (i.e. you build a proxy), but its somewhat involved to do that.

So what does Objective-C offer to help you to your goal?

Objective-C supports categories which allow you to add additional methods to an existing class, and hence all instances of an existing class.

But you don't want to add a method, you want to an an int. However you can define an int property - and a property by default is just two methods and some storage (in your case for the int). The category gives you the methods, so you just need the storage...

Enter associated objects. Objective-C supports associating any number of objects with another object, each associated object is identified by a unique key - effectively Objective-C gives you a dictionary of associated objects. And an object gives you storage...

So in outline you can

a) Declare a class with an int property - call it say MyAddedProperties

b) Define a category on CCSprite, say MyAddedPropertiesCategory, too provide your int property. Manually implement the setter and getter of this property to lookup and associated instance of MyAddedProperties and set/get its int property.

You've added a property to an existing class!

(b) requires to create and associate an instance of MyAddedProperties on first call of the categories setter/getter and to define a unique key for your associated object. You do the former by looking up your key and if there is no associated object create one. The unique key is any value of type void * - i.e. an address. The standard way to obtain a unique key is to declare a static variable (of any type, only its address is ever used) in your category and use its address as they key.

You can read about categories here and associated objects here.

It's not a lot of code. If you have trouble writing your solution ask a new question giving your code and what went wrong.

HTH

OTHER TIPS

You can wrap the sprite in the Character class :

@interface Character {
    CCSprite *sprite;
    int actionTag;
}

- (void)runAction:(CCAction *)action;

@end

and in the implementation file :

- (void)runAction:(CCAction *)action{
    actionTag = <action-name>;
    [sprite runAction:action];
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top