Reference : Method overloading in Objective-C?(stackoverflow)
(誤解を招く記載のため修正 2014/02/08 ナヨユキ)
引数の数が異なるメソッドのオーバーロード
単純な例を示します。クラスAが存在し、それぞれ引数の数が異なるメソッドを3つ用意し、main関数内でぞれぞれの引数が異なるメソッドを呼び出してみます。
/*************/ /* class A ***/ /*************/ @interface A : NSObject { } - (int) test1; - (int) test1: (int) a1; - (int) test1: (int) a1 arg2: (int) a2; @end; @implementation A //オーバーロードメソッド1(引数無し) - (int) test1 { printf("wow1.\n"); } //オーバーロードメソッド2(引数1つ) - (int) test1: (int) a1 { printf("wow2. arg1 = %d.\n", a1); } //オーバーロードメソッド3(引数3つ) - (int) test1: (int) a1 arg2: (int) a2 { printf("wow3. arg1 = %d. arg2 = %d\n", a1, a2); } @end /**********/ /* main ***/ /**********/ int main(void) { A* classA = [[A alloc] init]; [classA test1]; //引数無し [classA test1: 1]; //引数1つ [classA test1: 1 arg2: 2]; //引数2つ return 0; }
実行結果
wow1.
wow2. arg1 = 1.
wow3. arg1 = 1. arg2 = 2
wow2. arg1 = 1.
wow3. arg1 = 1. arg2 = 2
それぞれ引数の異なるメソッドを正しく呼び出せています。引数の数が異なる場合は問題なくオーバーロードが出来るようです。このあたり、Java/C++とは同じだと思います。
引数の型が異なるメソッドのオーバーロード
次に引数の型が異なるメソッドを定義してみます。
/*************/ /* class A ***/ /*************/ @interface A : NSObject { } - (int) test1; - (int) test1: (int) a1; //オーバーロード(int型の引数) - (int) test1: (int) a1 arg2: (int) a2; //オーバーロード(double型の引数) - (int) test1: (double) a1 arg2: (double) a2; @end;
このようにすると、コンパイル時に以下のエラーが出力されました。
error: duplicate declaration of method ‘-test1:arg2:’
むむむ。どうやら型で区別はされていないみたい。C++/Javaの場合はこのように型が異なる場合のオーバーロードは可能ですが、Objective-Cではこれが出来ないようです。では、型ではなく引数のラベル名を変更してみます。以下サンプルのオーバーロードメソッド3、4、5が該当します。
メソッド3と4は引数の型は同じで、ラベルが異なるパターン。
メソッド4と5は引数の型も、ラベルも異なるパターンになります。
/*************/ /* class A ***/ /*************/ @interface A : NSObject { } - (int) test1; - (int) test1: (int) a1; //オーバーロード3(ラベルが「arg2」) - (int) test1: (int) a1 arg2: (int) a2; //オーバーロード4(ラベルが「argg2」) - (int) test1: (int) a1 argg2: (int) a2; //オーバーロード5(ラベルが「arggg2」) - (int) test1: (double) a1 arggg2: (double) a2; @end; @implementation A // オーバーロードメソッド1 - (int) test1 { printf("wow1.\n"); } // オーバーロードメソッド2 - (int) test1: (int) a1 { printf("wow2. arg1 = %d.\n", a1); } // オーバーロードメソッド3 - (int) test1: (int) a1 arg2: (int) a2 { printf("wow3. arg1 = %d. arg2 = %d\n", a1, a2); } // オーバーロードメソッド4 - (int) test1: (int) a1 argg2: (int) a2 { printf("wow4. arg1 = %d. arg2 = %d\n", a1, a2); } //オーバーロードメソッド5 - (int) test1: (double) a1 arggg2: (double) a2 { printf("wow5. arg1 = %f. arg2 = %f\n", a1, a2); } @end /********** * main **********/ int main(void) { A* classA = [[A alloc] init]; [classA test1]; [classA test1: 1]; [classA test1: 1 arg2: 2]; //オーバーロード [classA test1: 3 argg2: 4]; //オーバーロード [classA test1: 5 arggg2: 6]; //オーバーロード return 0; }この場合、コンパイル時にはエラーが出ませんでした、
実行結果
wow1.
wow2. arg1 = 1.
wow3. arg1 = 1. arg2 = 2
wow4. arg1 = 3. arg2 = 4
wow5. arg1 = 5.000000. arg2 = 6.000000
wow2. arg1 = 1.
wow3. arg1 = 1. arg2 = 2
wow4. arg1 = 3. arg2 = 4
wow5. arg1 = 5.000000. arg2 = 6.000000
問題無く実行出来ています。結局の所、Objective-Cは型ではなく、メッセージセレクタ(ラベル)の違いによりオーバーロードが可能ということみたいです。Java/C++では引数の数、型で区別しているので、逆に同一の型の場合はオーバーロード出来ません。このあたり、使い方によっては便利(?)なのかもしれませんね。
セレクタのパラメータを省略したらどうなるんでしょ?
/********** * main **********/ int main(void) { A* classA = [[A alloc] init]; [classA test1]; [classA test1: 1]; [classA test1: 1 arg2: 2]; //オーバーロード [classA test1: 3 argg2: 4]; //オーバーロード [classA test1: 5 : 6]; //オーバーロード ←ココ return 0; }
コンパイル時に以下のワーニングが出力され、
overload.m: In function ‘main’:
overload.m:49: warning: ‘A’ may not respond to ‘-test1::’
overload.m:49: warning: (Messages without a matching method signature
overload.m:49: warning: will be assumed to return ‘id’ and accept
overload.m:49: warning: ‘...’ as arguments.)
overload.m:49: warning: ‘A’ may not respond to ‘-test1::’
overload.m:49: warning: (Messages without a matching method signature
overload.m:49: warning: will be assumed to return ‘id’ and accept
overload.m:49: warning: ‘...’ as arguments.)
そのまま、無視して実行してみると、実行時例外で落ちました。
なんとなく分かりました。省略した場合はid型になるらしいので、そんなメソッドは無いって事ですね。きっと。そして、実行しても存在しないから落ちるってことだと思います。
0 件のコメント :
コメントを投稿