简体   繁体   English

在子类中更改ivar的类(到派生类)

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

Assume I have two base classes, Container and Gizmo . 假设我有两个基类, ContainerGizmo Class Container has an instance variable of class Gizmo . Class Container有一个类Gizmo的实例变量。

Now I subclass Container (call that SubContainer ) and I also subclass Gizmo ( SubGizmo ). 现在我SubContainer Container (调用SubContainer ),我也是子类GizmoSubGizmo )。 In some of the methods of SubContainer I need to send a message to some properties that Gizmo doesn't have but SubGizmo does. SubContainer一些方法中,我需要向Gizmo没有的一些属性发送消息,但SubGizmo Is there any way to override the ivar to be of class SubGizmo in SubContainer , so I can send those messages? 有没有办法在SubContainer覆盖ivar为SubGizmo类,所以我可以发送这些消息?

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. 现在,每当我需要使用这样的属性或方法时,我可以通过将继承的ivar转换为SubGizmo来使其工作。

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. 最简单的方法是在Container中使用SubGizmo,而不是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. 但是,如果由于某种原因无法直接执行此操作,则可以在运行时修改SubContainer(查找class_addIvarclass_addMethod ,我可以在需要时给出示例),但这无助于避免Xcode的警告。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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