2010-04-27 8 views
5

Ich bin auf ein seltsames Problem in Objective-C, wenn ich zwei Klassen mit Initializern mit dem gleichen Namen, aber anders getippten Argumente. Zum Beispiel, sagen wir, ich Klassen A und B erstellen:Können Objective-C-Initialisierer den gleichen Namen verwenden?

A. h:

#import <Cocoa/Cocoa.h> 

@interface A : NSObject { 
} 

- (id)initWithNum:(float)theNum; 

@end 

a.m:

#import "A.h" 

@implementation A 

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

@end 

B.h:

#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; 
} 

Als ich dies ausführen, bekomme ich die folgende Ausgabe:

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 

Wenn ich die Reihenfolge der reversen Importe, so importiert es Bh zuerst, ich bekomme:

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 

Aus irgendeinem Grund scheint es, als ob es den Datentyp verwendet, der in jedem Interface definiert ist, das für beide Klassen zuerst eingefügt wird. Ich habe ein paar Schritte durch den Debugger gemacht und festgestellt, dass der isa-Zeiger für a- und b-Objekte identisch ist. Ich fand auch heraus, dass, wenn ich nicht mehr die alloc machen und init ruft inline, beide Initialisierungen scheinen richtig zu arbeiten, zum Beispiel:

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

Wenn ich diese Konvention verwenden, wenn ich a und b erstellen, erhalte ich das Recht Ausgabe und die isa Zeiger scheinen für jedes Objekt unterschiedlich zu sein.

Mache ich etwas falsch? Ich hätte gedacht, dass mehrere Klassen die gleichen Initialisierungsnamen haben könnten, aber das ist vielleicht nicht der Fall.

Antwort

5

Das Problem ist, dass die Methode +alloc ein Objekt vom Typ id zurückgibt, damit der Compiler nicht entscheiden kann, welche Methodensignatur verwendet werden soll. Sie können Ihre Anwendung zwingen, den richtigen Selektor auf verschiedene Arten auszuwählen. Eine wäre die Rückkehr von alloc zu werfen, so:

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

Oder Sie könnten alloc auf Ihrer Klasse überschreiben und zurück etwas speziellere, obwohl ich das nicht tun würde ich. Also:

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

Schließlich, und was würde ich persönlich ausgewählt haben, machen die Wähler mehr beschreibend:

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

// B.h 
- (id)initWithInteger:(int)theNum; 
+1

Sie können auch statische 'typeWithArgument hinzu:' Methoden, wie '[NSNumber numberWithInt:]' zu disambiguate. – drawnonward

+0

Laut der Dokumentation sollte der 'isa'-Ivar gesetzt werden, wenn Sie' + [NSObject alloc] 'aufrufen. Da Objective-C-Nachrichtenmeldungen zur Laufzeit aufgelöst werden, ist es nicht der Job der Laufzeit, nicht der Job des Compilers, um herauszufinden, was '+ [A alloc]' verrechnet? –

+0

@Nick Forge: Die Implementierung ist dynamisch gebunden, so dass dies kein Problem ist (und dies gilt auch hier, da der NSLog A und B wie erwartet anzeigt). Wenn der Compiler beteiligt ist, baut er den Aufruf von obj_msgSend auf. In diesem Fall verwendet ein Selektor einen Fließkommawert, während der andere eine Ganzzahl verwendet, und der Compiler erzeugt verschiedene Anweisungen (speichert das int in einem Ganzzahlregister und das Gleitkomma in einem fp-Register). Aus diesem Grund findet die Implementierung der Methode fehlerhafte Daten, wenn sie im erwarteten Register aussieht. –

Verwandte Themen