Methodenüberladung in Objective-C?

131

Meines Wissens unterstützt Objective-C keine Methodenüberladung. Was kann die Alternative dazu in Objective-C sein? Oder sollte ich immer einen anderen Methodennamen verwenden?

suse
quelle

Antworten:

193

Richtig, Objective-C unterstützt keine Methodenüberladung, daher müssen Sie unterschiedliche Methodennamen verwenden.

Beachten Sie jedoch, dass der "Methodenname" die Schlüsselwörter für die Methodensignatur enthält (die Parameternamen, die vor den ":" stehen). Es handelt sich also um zwei verschiedene Methoden, obwohl beide mit "writeToFile" beginnen:

-(void) writeToFile:(NSString *)path fromInt:(int)anInt;
-(void) writeToFile:(NSString *)path fromString:(NSString *)aString;

(Die Namen der beiden Methoden lauten "writeToFile: fromInt:" und "writeToFile: fromString:").

David Gelhar
quelle
4
@RaheelSadiq Es wird nicht überladen, da die Methodennamen (in ObjC: 'Selektoren') unterschiedlich sind. Da er anders ist, wird keiner als "überlastet" angesehen. Wenn writeToFile: ab: zweimal definiert wurden, wobei nur die Parameter - Typen unterschiedlich sind, dann wäre das eine Überlastung sein. Wie bereits erwähnt, wird dies in ObjC nicht wie in anderen Sprachen wie Java und jetzt Swift unterstützt.
Chris Hatton
Nicht nur die Parameternamen selbst, sondern auch die Doppelpunkte sind Teil des Methodennamens, sodass - (void) writeToFile: (NSString *) path: (int) anInt; und - (void) writeToFile: (NSString ) path: (NSString ) aString; sind ebenfalls verschiedene Methoden.
Kaiserludi
22

Es kann erwähnenswert sein, dass Clang + LLVM , selbst wenn Objective-C das Überladen von Methoden nicht unterstützt , das Überladen von Funktionen für C unterstützt. Obwohl dies nicht ganz das ist, wonach Sie suchen, kann es sich in einigen Situationen als nützlich erweisen (z. B. wenn Implementierung einer leicht gehackten (gegen die Kapselung gerichteten) Version des Besucherdesignmusters )

Hier ist ein einfaches Beispiel für die Funktionsüberladung:

__attribute__((overloadable)) float area(Circle * this)
{
    return M_PI*this.radius*this.radius;
}

__attribute__((overloadable)) float area(Rectangle * this)
{
    return this.w*this.h;
}

//...
//In your Obj-C methods you can call:
NSLog(@"%f %f", area(rect), area(circle));
Valentin Radu
quelle
Man könnte denken, dass dieser Hinweis in Kombination mit dem Methoden-Swizzling tatsächlich zu "überladbaren" Methoden führen könnte ... Warum man mit idund isKindOfClass:zur Verfügung stehen müsste , ist eine andere Geschichte ...
Alex Gray
1
@alexgray Ich verstehe Ihren Standpunkt idund isKindOfClass:decke die meisten praktischen Szenarien ab. Ein Grund, warum Sie möglicherweise eine Überladung bevorzugen, ist die automatische Auswahl des speziellsten Typs, für den ein geringer Aufwand für die explizite Typprüfung anfällt.
Chris Hatton
1
In der Clang-Dokumentation heißt es ausdrücklich, dass der C ++ - Name für C entstellt wird. Und das ist im Grunde genommen nur der Compiler, der automatisch hinter den Kulissen das tut, was man in Objective-C tut, indem er Methodennamen angibt, die sich durch Umfassen (in längerer Form) unterscheiden. die Argumenttypen.
Chris Stratton
19

David hat Recht, dass das Überladen von Methoden in Objective-C nicht unterstützt wird. In diesem Sinne ähnelt es PHP. Wie er auch betont, ist es üblich, zwei oder mehr Methoden mit unterschiedlichen Signaturen in der von ihm beispielhaften Weise zu definieren. Es ist jedoch auch möglich, eine Methode mit dem Typ "id" zu erstellen. Über den Typ "id" können Sie jedes Objekt (und alle Grundelemente mit der NSNumber-Klasse) an die Methode senden. Anschließend können Sie innerhalb der Methode selbst den Typ testen und bei Bedarf die entsprechende Ausnahme auslösen. Dies hat zwar nur einen geringen Leistungseinbruch, ist jedoch höchstwahrscheinlich nominal oder unbedeutend, es sei denn, Sie verarbeiten große Datenmengen.

- (void) writeToFile: (NSString *)path fromObject: (id)object {
    if (!([object isKindOfClass: [NSNumber class]] || [object isKindOfClass: [NSString class]])) {
         @throw [NSException exceptionWithName: @"InvalidArgumentException" reason: @"Unrecognized parameter type." userInfo: nil];
    }
}

Dies ist auch ein schöner Ort, um ein Protokoll zur Durchsetzung des Objekttyps zu implementieren. Dies kann folgendermaßen geschehen:

(id<MyProtocol>)object
Ziminji
quelle