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 件のコメント :
コメントを投稿