Перегрузка метода в Objective-C?

131

Насколько мне известно, Objective-C не поддерживает перегрузку методов. Что может быть альтернативой этому в Objective-C? Или мне всегда следует использовать другое имя метода?

SUSE
источник

Ответы:

193

Правильно, objective-C не поддерживает перегрузку методов, поэтому вам придется использовать разные имена методов.

Однако обратите внимание, что «имя метода» включает ключевые слова сигнатуры метода (имена параметров, стоящие перед символом «: »), поэтому ниже представлены два разных метода, даже если они оба начинаются с «writeToFile»:

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

(имена двух методов - «writeToFile: fromInt:» и «writeToFile: fromString:»).

Дэвид Гелхар
источник
4
@RaheelSadiq Это не перегружает, потому что имена методов (в ObjC: «селекторы») разные. Поскольку они разные, ни один из них не считается «перегруженным». Если writeToFile: from: были определены дважды, при этом различались только типы параметров , это было бы перегрузкой. Как уже говорилось, это не поддерживается в ObjC, как и в других языках, включая Java, а теперь и Swift.
Крис Хаттон
Не только сами имена параметров, но даже двоеточия являются частью имени метода, так что - (void) writeToFile: (NSString *) path: (int) anInt; и - (void) writeToFile: (NSString ) path: (NSString ) aString; также являются разными методами.
Kaiserludi
22

Возможно, стоит упомянуть, что даже если Objective-C не поддерживает перегрузку методов , Clang + LLVM поддерживает перегрузку функций для C. Хотя это не совсем то, что вы ищете, это может оказаться полезным в некоторых ситуациях (например, когда осуществление немного взломанный (идет вразрез с инкапсуляцией) версию этого дизайна посетитель шаблон )

Вот простой пример того, как работает перегрузка функций:

__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));
Валентин Раду
источник
Можно было бы подумать, что этот намек в сочетании со сменой методов действительно может привести к "перегружаемым" методам ... Зачем это нужно, имея idи находясь isKindOfClass:в распоряжении, - это совсем другая история ...
Алекс Грей
1
@alexgray Я понимаю вашу точку зрения idи isKindOfClass:охватываю большинство практических сценариев. Одна из причин, по которой вы можете предпочесть перегрузку, - это автоматический выбор наиболее конкретного типа, для которого требуется небольшая дополнительная нагрузка при явной проверке типов.
Крис Хаттон
1
Документация Clang прямо говорит, что то, что он делает, - это изменение имени C ++ для C. И это в основном просто компилятор, автоматически выполняющий за кулисами то же, что и в Objective-C, давая имена методов, которые отличаются охватывающими (в более длинной форме) типы аргументов.
Крис Стрэттон
19

Дэвид прав в том, что перегрузка метода не поддерживается в Objective-C. В этом смысле он похож на PHP. Как он также указывает, обычной практикой является определение двух или более методов с разными сигнатурами в том виде, в каком он их приводит. Однако также возможно создать один метод с использованием типа «id». С помощью типа «id» вы можете отправить любой объект (и любые примитивы, использующие класс NSNumber) в метод, а затем из самого метода вы можете проверить его тип и при необходимости вызвать соответствующее исключение. Хотя это незначительно снижает производительность, скорее всего, оно будет номинальным или незначительным, если вы не обрабатываете большие объемы данных.

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

Это также прекрасное место для реализации протокола, обеспечивающего соблюдение типа объекта, что можно сделать так:

(id<MyProtocol>)object
Ziminji
источник