Могу ли я указать конкретное требование суперкласса для переменной типа класса? - PullRequest
0 голосов
/ 23 августа 2010

Я делаю класс, который инициализирует экземпляры определенных классов.Этот класс будет использоваться для инициализации нескольких различных типов классов, все подклассы из общего суперкласса.В настоящее время я использую переменную экземпляра:

Class templateClass;

для хранения типа класса.Я получаю предупреждения компилятора о том, что templateClass не поддерживает методы.Есть ли способ подавить эти предупреждения или указать, что класс шаблона должен быть подклассом определенного класса?
Кроме того, это идеальный способ сделать это в target-c?Есть ли другой способ указать класс для использования, который я должен использовать?
Спасибо за помощь!

Редактирование: Класс, который я пишу, предназначен для создания спрайтов в случайно выбранных местах с несколькими переменнымиограничить их.Этот класс ожидает, что класс, который он перезаписывает, будет иметь метод initWithX:(int)pos yVariance:(int)variance.Я ожидаю, что это может быть определено с использованием протокалов, которые вы упомянули.Я буду делать несколько экземпляров класса rezzing для каждого типа спрайта, который я должен создать.Я хочу иметь возможность отправить класс перезадания initWithTemplateClass:(Class)templateClass, чтобы определить тип создаваемого спрайта.Я не уверен, что это правильный путь, потому что компилятор сообщает, что метод initWithX:(int)pos yVariance:(int)variance недоступен для templateClass.Я ожидаю, что есть проблема в том, как я собираюсь об этом.Код, который показывает предупреждение:

[self addChild:[[templateClass alloc] initWithX:positionOfChild  
  yVariance:(random()%(rowVarianceSize+1))]];

Ответы [ 2 ]

4 голосов
/ 23 августа 2010

Вы можете определить протокол со всеми необходимыми в нем методами. Затем объявите, что ваши классы соответствуют этому протоколу.

1 голос
/ 23 августа 2010

Отредактировано для добавления второй альтернативы

Я не получаю это предупреждение (и не ожидала этого), когда собираю простой тестовый пример, который пытается сделать то, что вы 'повторяю.

Тем не менее, то, что вы делаете, кажется вполне разумным.Хотя у вас есть утечка в примере 'addChild'.Вы распределяете / инициализируете свой новый объект, который оставляет его с счетом сохранения 1, а затем (при условии, что «self» является UIView), ваш вызов addChild также сохранит объект, но у вас нет собственной ссылки на освобождение.

id obj = [[templateClass alloc] initWithX:positionOfChild yVariance:(random()%(rowVarianceSize+1))]];
[self addChild:obj];
[obj release], obj = nil;

Кроме того, предложение Владимира определить протокол является хорошим, и если вы это сделаете, вы даже можете вставить проверку во время выполнения, что предоставленный вам templateClass соответствует этому протоколу.

if ([templateClass conformsToProtocol:@protocol(Foo)]) {
    id<Foo> obj = [[templateClass alloc] initWithX:positionOfChild yVariance:(random()%(rowVarianceSize+1))]];
    [self addChild:obj];
    [obj release], obj = nil;
} else {
    // Do whatever you want to do if templateClass isn't correct.
    // Obviously you could also have the protocol conformance check elsewhere.
}

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

Например:

@interface Sprite : UIView {
}
- (id)initWithX:(int)pos yVariance:(int)variance;
@end

@interface SpriteFactory {
}
- (Sprite*)createSprite;
@end

Затем создайте пары подклассов: подкласс Sprite и подкласс SpriteFactory, который создает этот вид спрайта.

Тогда вместо использования вашего Class templateClass у вас будет вместо этого «SpriteFactory * factory».

...