Изменение класса ивара (на производный класс) в подклассе
Предположим, у меня есть два базовых класса, 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 для отправки обновлений на все ваши игровые контроллеры.