Как уже указывал jer , все методы Objective-C по сути являются виртуальными.Это особенность языка, которая не совсем совпадает с другими С-подобными языками.Тем не менее, основы шаблона шаблона все еще могут быть достигнуты в Objective-C, "вручную" заставляя подклассы реализовывать определенные функции.Например (используя соглашение в вашей связанной статье в Википедии):
@interface Game
{
int playersCount;
}
- (void)playOneGame:(int)numPlayers;
// "virtual" methods:
- (void)initializeGame;
- (void)makePlay:(int)player;
- (BOOL)endOfGame;
- (void)printWinner;
@end
@implementation Game
- (void)initializeGame { NSAssert(FALSE); }
- (void)makePlay:(int player) { NSAssert(FALSE); }
- (BOOL)endOfGame { NSAssert(FALSE); return 0; }
- (void)printWinner { NSAssert(FALSE); }
- (void)playOneGame:(int)numPlayers
{
//..
}
@end
Приведенный выше код заставляет подклассы Game
переопределять «виртуальные» методы, вызывая исключение в момент реализации одной из базовых классов.называется.По сути, это перемещает тест из стадии компилятора (как это было бы в C ++ или Java) в стадию времени выполнения (где подобные вещи часто выполняются в Objective-C).
Если вы на самом деле если вы хотите применить правило, согласно которому подклассам запрещается переопределять метод playOneGame:
, вы можете попытаться (*) проверить правильность реализации из метода init
:
@implementation Game
...
- (void)init
{
if ((self = [super init]) == nil) { return nil; }
IMP my_imp = [Game instanceMethodForSelector:@selector(playOneGame:)];
IMP imp = [[self class] instanceMethodForSelector:@selector(playOneGame:)];
NSAssert(imp == my_imp);
return self;
}
...
@end
(*) Обратите внимание, что этот код не дает 100% надежной защиты от подклассов, которые повторно реализуют playOneGame:
, так как сама природа Objective-C позволит подклассу переопределять instanceMethodForSelector:
для полученияправильный результат.