2012-04-30 1 views
4

Предположим, у меня есть два базовых класса: Container и Gizmo. Класс Container имеет переменную экземпляра класса Gizmo.Изменение класса ivar (на производный класс) в подклассе

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

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

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

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

+1

Программа была бы менее двусмысленной – justin

+2

Я рад, что вы, похоже, одобряете мои имена классов; буквы плюс некоторое количество звезд были слишком тяжелыми для меня, чтобы отслеживать. :) –

+0

@JacquesCousteau, который намного яснее :) – justin

ответ

2

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

@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 

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

+1

Это довольно опрятно, еще одна вещь, которую я видел, я могу сделать, это сделать SubGizmo * subg = (SubGizmo *) gizmo; в начале каждого метода, который будет отправлять такие сообщения. Я думаю, что они в значительной степени делают то же самое, в то время как ваш более глобальный. –

+0

@ Kaan yup, когда он используется в нескольких местах, он уменьшает количество шума и уменьшает количество изменений, которые вы должны внести, если они изменяются. – justin

0

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

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

+1

Вы не можете добавить ivar к существующему классу во время выполнения, class_addIvar предназначен только для незарегистрированных классов. Вы можете использовать objc_setAssociatedObject, хотя –

+0

@Matthias yes, но затем я хочу, чтобы в другом подклассе A (A ***) появился еще один экземпляр, принадлежащий другому подклассу B (B ***), вы видите, где я получаю –

+0

@ JoshuaWeinberg: Да, конечно, но я понял, что OP контролирует подкласс. – Matthias

1

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

+0

не работает, когда я пытаюсь получить доступ к свойствам с точечной нотацией. Я думаю, что я просто буду прикладывать к нужному подклассу каждый раз, когда я получаю доступ к чему-то, чего нет у базового класса. Спасибо за помощь в любом случае. –

-2

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