Przeciążanie metod w Objective-C?

132

O ile mi wiadomo, Objective-C nie obsługuje przeciążania metod. Jaka może być alternatywa dla tego w Objective-C? Czy powinienem zawsze używać innej nazwy metody?

suse
źródło

Odpowiedzi:

195

Prawidłowo, cel-C nie obsługuje przeciążania metod, więc musisz używać różnych nazw metod.

Należy jednak pamiętać, że „nazwa metody” zawiera słowa kluczowe sygnatur metody (nazwy parametrów występujące przed „:” s), więc poniższe są dwiema różnymi metodami, mimo że obie zaczynają się od „writeToFile”:

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

(nazwy tych dwóch metod to „writeToFile: fromInt:” i „writeToFile: fromString:”).

David Gelhar
źródło
4
@RaheelSadiq Nie jest to przeciążenie, ponieważ nazwy metod (w ObjC: „selektory”) są różne. Ponieważ żaden z nich jest inny, nie jest uważany za „przeciążony”. Jeśli writeToFile: from: zostało zdefiniowane dwukrotnie, z różnymi typami parametrów , to byłoby to przeciążenie. Jak już wspomniano, nie jest to obsługiwane w ObjC, tak jak w innych językach, w tym w Javie, a teraz w Swift.
Chris Hatton
Nie tylko same nazwy parametrów, ale nawet dwukropki są częścią nazwy metody, więc - (void) writeToFile: (NSString *) path: (int) anInt; i - (void) writeToFile: (NSString ) path: (NSString ) aString; to także różne metody.
Kaiserludi
22

Warto wspomnieć, że nawet jeśli Objective-C nie obsługuje przeciążania metod , Clang + LLVM obsługuje przeciążanie funkcji dla C. Chociaż nie jest to dokładnie to, czego szukasz, może się okazać przydatne w niektórych sytuacjach (na przykład, gdy wykonawczych lekko posiekany (sprzeczne hermetyzacji) wersję tego wzorca projektowego gość )

Oto prosty przykład, jak działa przeciążanie funkcji:

__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
źródło
Można by pomyśleć, że ta wskazówka, w połączeniu ze swizzlingiem metod, może rzeczywiście prowadzić do "przeciążalnych" metod ... Dlaczego jednak trzeba, z idi isKindOfClass:do dyspozycji, to inna historia ...
Alex Gray
1
@alexgray Rozumiem twój punkt widzenia idi omawiam isKindOfClass:większość praktycznych scenariuszy. Jednym z powodów, dla których możesz preferować przeładowanie, jest automatyczny wybór najbardziej konkretnego typu, który jest obsługiwany, co wiązałoby się z niewielkim narzutem przy jawnym sprawdzaniu typu.
Chris Hatton,
1
Dokumentacja Clang wyraźnie mówi, że to, co robi, to zniekształcanie nazw w C ++ dla C.A to po prostu kompilator automatycznie wykonujący za kulisami to, co robi się w Objective-C, nadając metodom nazwy, które różnią się przez obejmowanie (w dłuższej formie) typy argumentów.
Chris Stratton,
19

David ma rację, ponieważ przeciążanie metody nie jest obsługiwane w Objective-C. W tym sensie jest podobny do PHP. Jak również podkreśla, powszechną praktyką jest definiowanie dwóch lub więcej metod z różnymi podpisami w sposób, w jaki podaje przykłady. Możliwe jest jednak również utworzenie jednej metody przy użyciu typu „id”. Poprzez typ „id” możesz wysłać dowolny obiekt (i wszelkie prymitywy używające klasy NSNumber) do metody, a następnie z poziomu samej metody możesz przetestować jej typ i zgłosić odpowiedni wyjątek, jeśli to konieczne. Chociaż powoduje to niewielki spadek wydajności, najprawdopodobniej będzie to nominalne lub nieistotne, chyba że przetwarzasz duże ilości danych.

- (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];
    }
}

Jest to również piękne miejsce na zaimplementowanie protokołu wymuszającego typ obiektu, co można zrobić w następujący sposób:

(id<MyProtocol>)object
Ziminji
źródło