Метод перевантаження в Objective-C?


131

Наскільки мені відомо, Objective-C не підтримує метод перевантаження. Що може бути альтернативою для цього в Objective-C? Або я завжди повинен використовувати іншу назву методу?

Відповіді:


193

Правильний, aim-C не підтримує перевантаження методу, тому вам доведеться використовувати різні назви методів.

Однак зауважте, що "ім'я методу" включає ключові слова підпису методу (назви параметрів, що надходять до ":" s), тож наступні два різні методи, хоча вони обидва починають "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 *) шлях: (int) anInt; та - (void) writeToFile: (NSString ) шлях: (NSString ) aString; також різні методи.
Кайзерлуді

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.