2012-01-05 11 views
1

_somethingへの呼び出しがfooから呼び出されて、呼び出しBの実装が_somethingになるのはなぜですか?面白いObjective-cメソッドの動作

@interface A 
@end 

@implementation A 
- (void) _something { 
    NSLog(@"A"); 
} 
- (void) foo { 
    [self _something]; 
} 
@end 

@interface B : A 
@end 

@implementation B 
- (void) _something { 
     NSLog(@"B"); 
} 
@end 
+1

'foo'とは何ですか? 'A'オブジェクトまたは' B'オブジェクト? –

+0

@MichaelDautermann 'foo'は、クラス' A'が応答するメッセージです。 – SundayMonday

答えて

2

それはBクラスのオブジェクトに対して呼び出された場合にのみBの実装を呼び出します。 これは、objective-Cでは、すべてのメソッドが「実質的に」(かなり単純化されていますが)、基本的にはdynamic dispatchであるためです。

より正確にするために、Objective-Cにはメソッドがありません。代わりに、オブジェクトに "メッセージ"を送ります。実行時に処理され、オブジェクト自身がこのメッセージにどのように応答するかを決定します。デフォルトでは、クラス内のセレクタを検索し、関連付けられた「メソッド」(_somethingがAとBで異なる場合)を呼び出します。

1

オブジェクトがBの場合は、_somethingと呼ばれるので、B_somethingというコードが表示されます。 Aの実装を期待していたら、objective-Cメッセージの受け渡しを誤解しています。メソッドのコードは実行時に決定されます。 C++から来た場合、すべてのメソッドが仮想であると想像してください。

1

あなたはクラスBのオブジェクトに_somethingと呼ばれるならば、あなたは、本質的にそれを上書きしました:

B *myClass = [B alloc] init]; 
[myClass _something]; 

出力:

B 

は、次の例を行っていた、あなたは意志_somethingをオーバーライドしておらず、クラスAの出力を得る:

A *myClass = [A alloc] init]; 
[myClass _something]; 

出力:

A *myClass = [B alloc] init]; 
[myClass _something]; 

出力:

それは本当にによるメッセージの動的な性質のために、あなたのオブジェクトをインスタンス化してきた元のクラスに依存

A 

B 
2

つまり、Bが-_somethingメソッドをオーバーライドしているため、Bのインスタンスに対して-fooを呼び出すとします。

メソッドディスパッチはメッセージ送信によってObjective-Cで実装されるため、fooメソッドは_somethingを実行するように受信者にメッセージを送信します。受信者(または受信者に代わってランタイム)は、メッセージに応じて何をするかを調べます。メッセージはメソッドセレクタを指定し、オブジェクトは対応するの実装を実行します。クラスAとクラスBのための_somethingの異なる実装があります。

関連する問題