objective-cクラスメソッドの使い方で、多重定義のところが腑に落ちなかったのですが、一応氷解したので、記録として。
C++ の場合、次のようにメソッドの多重定義ができます。
class A { public: void print( int x ); void print( char *s ); };
int型の引数を持つ場合と、char*型の引数を持つ場合の関数を「print」という同じ名前が使えるわけです。C言語の場合は「printInt」、「printString」なんて名前を変えないといけないので、この多重定義は名前を定義する際に非常に重要な機能なのです。
これを、「素直」にobjective-c の文法に直そうとすると、
@interface A : NSObject - (void)print:(int)x ; - (void)print:(char*)s ; @end
と書きたいところですが、、、できません。名前が重複してる(duplicate declaration of method ‘-print:’)なるエラーが出ます。
実は、objective-cのメソッドの書き方は、
– メソッド名 :(型)仮引数 :(型)仮引数 ;
なのかと思い込んでいたのですが、実は違います。
最初の単語も含めて、キーワードと仮引数のペアなんですなぁ。
– キーワード:(型)仮引数 キーワード:(型)仮引数 ;
と考えるのが正しいのです。
で、objective-cの場合は、型の違いをチェック判別せずに、キーワードの違いで判別します。そんな訳で、
– print:(int)x :(int)y ;
– print:(int)x z:(int)z ;
の2つはキーワード無しと、キーワードあり「z」のメソッドとして違いが認識されます。
ですが、最初のキーワードと型のペア
– print:(int)x;
– print:(char*)s;
の2つは、同じ print というキーワードを使っているので「重複(duplicate)」ってな訳で、コンパイルエラーになるのです。
# objective-c のサンプルコードを見て、妙なメソッドの名前の付け方をしてる
# なあ、と思っていたら、そういう理由があったんですね…
#import <stdio.h> #import <Foundation/Foundation.h> #import <Foundation/NSObject.h> @interface A : NSObject - (void)print ; //- (void)print :(void) ; // できない - (void)print:(int)x ; //- (void)print:(char*)s ; // 重複するためできない - (void)print:(int)x :(int)y ; - (void)print:(int)x z:(int)z ; // キーワードで区別できる @end #if 0 // C++の場合 class A { public: // void print(); void print( void ); // print()と同じ意味 void print( int x ); void print( char *s ); void print( int x, int y ); // void pritn( int x, int z ); // できない }; #endif @implementation A - (void)print { printf("in print\n"); } - (void)print:(int)x { printf("in print x\n"); } - (void)print:(int)x :(int)y { printf("in print x y\n"); } /* - (void)print:(char*)s { printf("in print s\n" ); } */ - (void)print:(int)x z:(int)z { printf("in print x z\n"); } @end int main( void ) { printf("hello3.m\n" ); A *a = [A new]; [a print]; [a print :1]; [a print :1 :2 ]; [a print :1 z:2 ]; [a release]; return 1; } /** 実行結果 hello3.m in print in print x in print x y in print x z **/
そんな訳で、ひとつの引数だけの場合は、実質、多重定義ができません。C言語のように「printInt」、「printString」としてメソッド名で区別をさせます。
# 実に「対称性」が悪い!と思うのは私だけではないハズ。
# ただ、objective-cの発祥時期を考えると、Cリンケージの考慮から、こういう形に
# なっているのだと思う。リンカーに対して厳密な名前を使うC++に対して(C言語自体
# のリンケージはかなり緩い)、objective-cはそのままC言語のリンクを使うように
# したので、こういう結果になったのでは?