Pregunta

Assume I have two base classes, Container and Gizmo. Class Container has an instance variable of class Gizmo.

Now I subclass Container (call that SubContainer) and I also subclass Gizmo (SubGizmo). In some of the methods of SubContainer I need to send a message to some properties that Gizmo doesn't have but SubGizmo does. Is there any way to override the ivar to be of class SubGizmo in SubContainer, so I can send those messages?

Right now I can make it work by casting my inherited ivar to SubGizmo every time I need to use such a property or method.

Here is why I want such a behavior: I already have a game that works, but the more modes I add, the harder it gets to maintain. If I want to change/add a method that will run on each mode; I would need to go to three different game - controller objects and make the change.

By subclassing, I wanted to keep the main game mechanics in the base classes and create a subclass for each mode. this way a change I make in a base class would reflect on each mode. However each controller and game object have new methods for different modes, and they send messages to each other. This is where my problem is arising from.

¿Fue útil?

Solución

just introduce type safety and conversion logic using an approach like this:

@interface SubContainer ()

- (SubGizmo *)subGizmo;
// setter is often unnecessary
- (void)setSubGizmo:(SubGizmo *)pSubGizmo;

@end

@implementation SubContainer

...

- (SubGizmo *)subGizmo
{
    Gizmo * ret = self.gizmo;
    // sanity check the type to ensure this is properly initialized,
    // or return nil if holding a Gizmo is valid in this context:
    assert([ret isKindOfClass:[SubGizmo class]]);
    return (SubGizmo *)ret;
}

- (void)setSubGizmo:(SubGizmo *)pSubGizmo
{
    self.gizmo = pSubGizmo;
}

- (void)addWater
{
  [self.subGizmo addWater];
}

@end

however, the creeping complexity suggests more variations in types is worth consideration.

Otros consejos

just use type id for your ivar, you only have to include the proper header file to avoid warnings.

The easiest way would be to use SubGizmo in Container, not Gizmo. :-)

However, if you can't do that directly for some reason, you can modify SubContainer at runtime (seek for class_addIvar or class_addMethod, I can give you an example when you need it), but that does not help to avoid Xcode's warning.

You canu use NSNotifications for sending updates to all your game controllers.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top