Изменение класса ивара (на производный класс) в подклассе

Предположим, у меня есть два базовых класса, Container а также Gizmo, Учебный класс Container имеет переменную экземпляра класса Gizmo,

Теперь я подкласс Container (позвони SubContainer) и я тоже подкласс Gizmo (SubGizmo). В некоторых из методов SubContainer Мне нужно отправить сообщение в некоторые свойства, которые Gizmo не имеет но SubGizmo делает. Есть ли способ переопределить ивар, чтобы быть класса SubGizmo в SubContainerтак я могу отправлять эти сообщения?

Прямо сейчас я могу заставить это работать, бросая мой унаследованный ivar к SubGizmo каждый раз, когда мне нужно использовать такое свойство или метод.

Вот почему я хочу такого поведения: у меня уже есть игра, которая работает, но чем больше режимов я добавляю, тем сложнее ее поддерживать. Если я хочу изменить / добавить метод, который будет работать в каждом режиме; Мне нужно было бы перейти к трем различным игровым объектам контроллера и внести изменения.

Подклассами я хотел сохранить основные игровые механизмы в базовых классах и создать подкласс для каждого режима. таким образом, изменения, которые я делаю в базовом классе, отражаются на каждом режиме. Однако у каждого контроллера и игрового объекта есть новые методы для разных режимов, и они отправляют сообщения друг другу. Это где моя проблема возникает.

4 ответа

Решение

Просто введите безопасность типов и логику преобразования, используя такой подход:

@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

тем не менее, сложность ползучести предполагает, что больше вариантов в типах заслуживает рассмотрения.

Просто используйте идентификатор типа для вашего ivar, вам нужно только включить правильный заголовочный файл, чтобы избежать предупреждений.

Самый простой способ - использовать SubGizmo в контейнере, а не в Gizmo.:-)

Однако, если вы не можете сделать это напрямую по какой-либо причине, вы можете изменить SubContainer во время выполнения (ищите class_addIvar или же class_addMethodЯ могу привести пример, когда вам это нужно), но это не помогает избежать предупреждения XCode.

Вы можете использовать NSNotifications для отправки обновлений на все ваши игровые контроллеры.

Другие вопросы по тегам