web-dev-qa-db-ja.com

Objective-Cで純粋な仮想メソッドを実装する

そこへ行きたいです。しかし真剣に、どのようにして「アップル」の方法で純粋な仮想メソッドを実装するのですか?基本クラスでプロトコルを使用し、それらのメソッドで例外をスローしますか?

41
Chris

Objective-Cでプログラミングするときは、仮想メソッドなどのことを気にする必要があります。 Objective-Cオブジェクトのメソッドを呼び出すのではなく、オブジェクトにメッセージを送信します。オブジェクトはメッセージに応答するか応答しないかのいずれかですが、動的バインディングのため、実行時までこれを知ることができません。

したがって、ベースオブジェクトでメソッドを宣言し、実装を提供せず、問題はない(コンパイラの警告を除く)ことができますが、そのようなメソッドを使用してオブジェクトを直接インスタンス化すると、コンパイラフラグを立てることはできません。実際にそのメッセージをオブジェクトに送信しない限り、実行時にエラーをスローしません。

(私の意見では)「仮想」基本クラスを作成する最良の方法は、メソッドを宣言し、それに適切な例外をスローするスタブ実装を与えることです。

55
JeremyP

Objective-Cでは、C++のような純粋な仮想サポートはありません。

シミュレーションでは、インターフェイスでメソッドを宣言しますが、.mファイルには実装しません。もちろん、コンパイラの警告が表示されますが、IIRCでは警告をオフにできます。ただし、C++(IIRC)で取得するサブクラスでそれらを上書きしない場合、警告/エラーは表示されません。

代わりの方法は、NSAssert(NO, @"Subclasses need to overwrite this method");本体のみで実装することです。それでも、コンパイル時にではなく、実行時にのみこれをキャッチします。

33
DarkDust

デリゲートパターンは、デリゲートがid<YourDelegateProtocol>として定義されているサブクラスよりも適切な場合があります。デリゲートプロトコルで必要なメソッドが実装されていない場合、コンパイラは警告を生成します。

Objective-Cでは、オブジェクトは複数のスーパークラスから継承できませんが、複数のプロトコルを実装できるため、サブクラス化は一般的に回避されます。

7
Matt Stevens

以下を使用する必要があります。

- (void)doesNotRecognizeSelector:(SEL)aSelector method. 

Appleが述べたように、ここ: https://developer.Apple.com/library/mac/#documentation/cocoa/reference/Foundation/Classes/NSObject_Class/Reference/Reference.html

6
Antony Clements

あなたにはいくつかの選択肢がありますが、あなたは正しい軌道に乗っています。

ObjCはこれを直接サポートしていません。サブクラスにプロトコルを実装させることは、コンパイル時にプロトコルをチェックするための最良の方法です。

基本クラスにメソッドを「密かに」実装してアサートすることは、サブクラスが実行時に正しくサブクラス化されたことを確認するために行うことです。一部の人々はアサーションについて複雑な感情を持っているか、アクティブにしておかなければならないので、それは常に良い解決策ではありません。

コンパイラの警告でインスタンスが切断されない場合に備えて、サブクラスが特定のクラスコンストラクタと初期化シーケンスを使用するように強制し、インスタンスを返す前に必要なすべてが実装されていることを確認することもできます。

しかし、ObjCには、クライアントが自分の足で撃つことを可能にする、または彼らが望むものを回避することができるいくつかのlang機能がありません...それを強制することに行き詰まってはいけません。

注:ObjCでは例外は非常に一般的ではありません(そして少し安全でもありません)。

2
justin

仮想メソッドは、同じシグニチャー(つまり、同じ数のparamsとtypeのparamsを持つ)を持つ関数によって、継承するクラス内でその動作をオーバーライドできるメソッドです。

例:-

@implementation BaseClass

-(void)viewDidLoad
{
 [self virtualMethod:123];
}

-(void)virtualMethod:(int)param
{
 //implement this method in subclass
}

@end

////////////////////////////////////////////////// //

@interface ChildClass:BaseClass
@end

@implementation ChildClass

-(void)virtualMethod:(int)param
{
 NSLog(@"There is no keyword "Virtual" in Objective C.");
}
@end

出力:-

「Objective Cには「Virtual」というキーワードはありません。」

0
Deepak