简体   繁体   中英

Changing the class of an ivar (to a derived class), in a subclass

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.

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.

只需使用ivar的类型ID,您只需要包含正确的头文件以避免警告。

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.

您可以使用NSNotifications将更新发送到所有游戏控制器。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM