5

同じ名前の初期化子を使用しているが、引数の型が異なる 2 つのクラスがあると、Objective-C で奇妙な問題が発生します。たとえば、クラス A と B を作成するとします。

あ:

#import <Cocoa/Cocoa.h>

@interface A : NSObject {
}

- (id)initWithNum:(float)theNum;

@end

午前:

#import "A.h"

@implementation A

- (id)initWithNum:(float)theNum
{
    self = [super init];
    if (self != nil) {
        NSLog(@"A: %f", theNum);
    }
    return self;
}

@end

Bh:

#import <Cocoa/Cocoa.h>

@interface B : NSObject { 
}

- (id)initWithNum:(int)theNum;

@end

Bm:

#import "B.h"

@implementation B

- (id)initWithNum:(int)theNum
{
    self = [super init];
    if (self != nil) {
        NSLog(@"B: %d", theNum);
    }
    return self;
}

@end

main.m:

#import <Foundation/Foundation.h>

#import "A.h"
#import "B.h"

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    A *a = [[A alloc] initWithNum:20.0f];   
    B *b = [[B alloc] initWithNum:10];

    [a release];
    [b release];

    [pool drain];
    return 0;
}

これを実行すると、次の出力が得られます。

2010-04-26 20:44:06.820 FnTest[14617:a0f] A: 20.000000
2010-04-26 20:44:06.823 FnTest[14617:a0f] B: 1

インポートの順序を逆にして、最初に Bh をインポートすると、次のようになります。

2010-04-26 20:45:03.034 FnTest[14635:a0f] A: 0.000000
2010-04-26 20:45:03.038 FnTest[14635:a0f] B: 10

何らかの理由で、@interface が最初に両方のクラスに含まれる方で定義されたデータ型を使用しているようです。デバッガーをいくつかステップ実行したところ、a オブジェクトと b オブジェクトの両方の isa ポインターが同じ結果になることがわかりました。また、alloc 呼び出しと init 呼び出しをインラインにしなくなった場合、両方の初期化が適切に機能しているように見えることもわかりました。

A *a = [A alloc];
[a initWithNum:20.0f];

a と b の両方を作成するときにこの規則を使用すると、正しい出力が得られ、isa ポインターはオブジェクトごとに異なるように見えます。

私は何か間違ったことをしていますか?複数のクラスが同じ初期化子名を持つ可能性があると思っていましたが、おそらくそうではありません。

4

1 に答える 1

5

問題は、+allocメソッドが型のオブジェクトを返すidため、コンパイラが使用するメソッドシグネチャを決定できないことです。さまざまな方法で、アプリケーションに正しいセレクターを選択させることができます。1つは、allocからのリターンをキャストすることです。

A* a = [(A*)[A alloc] initWithNum:20.f];
B* b = [(B*)[B alloc] initWithNum:10];

または、クラスのallocをオーバーライドして、より具体的なものを返すこともできますが、これは自分では行いません。それで:

+ (A*)alloc { return [super alloc]; }

最後に、私が個人的に選択したものを、セレクターをよりわかりやすくします。

// A.h
- (id)initWithFloat:(float)theNum;

// B.h
- (id)initWithInteger:(int)theNum;
于 2010-04-27T02:20:58.277 に答える