【问题标题】:Changing the class of an ivar (to a derived class), in a subclass在子类中更改 ivar 的类(到派生类)
【发布时间】:2012-05-09 20:49:44
【问题描述】:

假设我有两个基类,ContainerGizmoContainer 类有一个 Gizmo 类的实例变量。

现在我继承了Container(称为SubContainer),我也继承了GizmoSubGizmo)。在SubContainer 的某些方法中,我需要向Gizmo 没有但SubGizmo 有的一些属性发送消息。有什么方法可以将 ivar 覆盖为 SubContainer 中的 SubGizmo 类,以便我可以发送这些消息?

现在每次我需要使用这样的属性或方法时,我都可以通过将继承的 ivar 转换为 SubGizmo 来使其工作。

这就是我想要这种行为的原因:我已经有一个可以运行的游戏,但是我添加的模式越多,它就越难维护。如果我想更改/添加将在每种模式下运行的方法;我需要转到三个不同的游戏 - 控制器对象并进行更改。

通过子类化,我想将主要游戏机制保留在基类中,并为每种模式创建一个子类。这样,我在基类中所做的更改将反映在每种模式上。然而,每个控制器和游戏对象都有针对不同模式的新方法,并且它们相互发送消息。这就是我的问题所在。

【问题讨论】:

  • 一个程序不会那么模棱两可
  • 我很高兴你似乎同意我的班级名称;字母加上一些星星对我来说太难追踪了。 :)
  • @JacquesCousteau 这更清楚:)

标签: objective-c ios inheritance subclass ivars


【解决方案1】:

只需使用如下方法引入类型安全和转换逻辑:

@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

然而,逐渐复杂的复杂性表明更多类型的变化值得考虑。

【讨论】:

  • 这很简洁,我看到我可以做的另一件事是做 SubGizmo * subg = (SubGizmo* ) gizmo;在将发送此类消息的每个方法的开头.. 我认为他们几乎做同样的事情,而你的更全球化。
  • @Kaan 是的,当它在多个地方使用时,它会减少很多噪音并减少您在更改时必须进行的更改次数。
【解决方案2】:

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

【讨论】:

  • 当我尝试使用点符号访问属性时,不起作用。我想我每次访问基类没有的东西时都会坚持转换为想要的子类。无论如何感谢您的帮助
【解决方案3】:

最简单的方法是在 Container 中使用 SubGizmo,而不是 Gizmo。 :-)

但是,如果你因为某种原因不能直接这样做,你可以在运行时修改SubContainer(求class_addIvarclass_addMethod,你需要的时候我可以给你一个例子),但这并不有助于避免 Xcode 的警告。

【讨论】:

  • 您不能在运行时将 ivar 添加到现有类,class_addIvar 仅适用于未注册的类。你可以使用 objc_setAssociatedObject
  • @Matthias 是的,但是我希望 A ( A***) 的另一个子类有另一个实例,该实例属于 B ( B*** ) 的另一个子类,你知道我在哪里
  • @JoshuaWeinberg:是的,当然,但我知道 OP 可以控制子类。
【解决方案4】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 2018-03-21
    • 1970-01-01
    相关资源
    最近更新 更多