ここにテンプレートメソッド patternがあり、Java と C++ は仮想関数を使用して簡単に実装できます。このパターンを実装するオブジェクト C はどうですか? ココアタッチ(iOS)の例はありますか?
3 に答える
jerがすでに指摘しているように、すべてのObjective-Cメソッドは本質的に仮想です。これは、他の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
は、基本クラスの実装の1つが呼び出された瞬間に例外をスローすることにより、のサブクラスに「仮想」メソッドをオーバーライドするように強制します。事実上、これにより、テストがコンパイラー段階(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
(*)Objective-Cの性質上、正しい結果を生成するためにplayOneGame:
サブクラスをオーバーライドできるため、このコードは、再実装するサブクラスに対する100%の堅固な防御にはならないことに注意してください。instanceMethodForSelector:
Objective-C では、すべてのメソッドが C++virtual
メソッドに似ています。