Подтвердить что ты не робот

Расширение класса Objective-C

Как довольно новый программист objective-c (с опытом работы в течение 4 лет), похоже, мне сложно понять, когда использовать расширения класса. Из того, что я понял (и, пожалуйста, исправьте меня, если я ошибаюсь), основное различие между категориями и расширениями состоит в том, что расширение предполагает, что вы реализуете методы внутри своей основной реализации, тогда как с категорией это может быть в другой реализации, Также кажется, что люди используют расширения, главным образом, для частных методов.

Вот мой первый вопрос. Какая разница между использованием расширения класса для объявления частного метода, а не объявлением его вообще (он, похоже, скомпилирован в обоих случаях)? (пример 1 против 2)

Пример 1

@interface Class()
-(void) bar;
@end

@implementation Class
-(void) foo {
    [self bar];
}

-(void) bar {
    NSLog(@"bar");
}
@end

Пример 2

@implementation Class
-(void) foo {
    [self bar];
}

-(void) bar {
    NSLog(@"bar");
}
@end

Второй вопрос: Какая разница между объявлением иваров внутри расширения и объявлением его непосредственно внутри реализации? (Пример 3 против 4)

Пример 3

@interface Class() {
    NSArray *mySortedArray;
}
@end

@implementation Class
@end

Пример 4

@implementation Class
NSArray *mySortedArray;
@end

У меня есть последний вопрос о соглашениях о кодировании: когда я должен поставить знак подчеркивания (_) перед именем переменной?

Спасибо

4b9b3361

Ответ 1

Методы расширения класса

Никогда не случалось так, что вам не нужно было объявлять свои частные методы. До недавнего времени вам нужно было где-то объявлять свои частные методы, и большинство людей выбрали расширение класса для этого. Из Xcode 4.4 (я считаю) компилятор достаточно умен, чтобы определить, какие методы должны быть частными в рамках этой реализации, устраняя необходимость объявления их в другом месте.

Переменные в расширениях классов

Как и для примеров 3 и 4, будьте осторожны. Внутри расширения класса переменная является переменной экземпляра для этого класса (пример 3). Пример 4 объявляет глобальную переменную (из-за того, что она следует глобальной семантике переменных из C). Придерживайтесь примера 3 для ваших частных переменных экземпляра.

Соглашения о кодировании

Что касается соглашения о кодировании, то разработчику/команде решать, использовать ли подчеркивание или нет. Наша команда использует m_ для частных переменных экземпляра. Apple в своей документации, используя символы подчеркивания (что стиль именования для базовых переменных экземпляра для синтезированных свойств). Важно, быть последовательным во всем коде.

Ответ 2

Основное различие между категориями и расширениями состоит в том, что расширение предполагает, что вы реализуете методы внутри своей основной реализации, тогда как с категорией это может быть в другой реализации. Также кажется, что люди используют расширения, главным образом, для частных методов.

Правильно.

В чем разница между использованием расширения класса для объявления частного метода и вообще не объявлять его (он, кажется, компилируется в обоих случаях)?

Возможно, просто предупреждение компилятора относительно незаявленного селектора. (Конечно, он работает нормально - метод реализован и существует.) Также обратите внимание, что для компилятора требуется декларация (известная, правильная сигнатура функции), чтобы испускать ABI-совместимый, правильный двоичный код. Предположение, что он делает о незаявленных методах (а именно, что они возвращают id и принимает переменные аргументы), может быть неверным - вызов функции с помощью указателя несовместимого типа - это поведение undefined.

Какая разница между объявлением ivars внутри расширения и объявлением его непосредственно внутри реализации?

В четвертом примере это глобальная переменная C, она не переменная экземпляра вашего класса.

когда я должен поставить знак подчеркивания (_) перед именем переменной?

Всякий раз, когда вы хотите, просто делайте это последовательно. Всегда или никогда.

Ответ 3

В вопросе 1, пример 2: Методы foo и bar, реализованные в классе, видны экземплярам класса. Если foo и bar не объявлены в отдельном файле заголовка И файл реализации не доступен, другой класс не будет знать о существовании foo и bar. foo и bar - частные методы; экземпляры класса будут реагировать на сообщения foo и bar. Кроме того, Xcode будет отмечать предупреждение, если другой класс, который пытается сообщить foo и bar, поскольку Xcode не может проверить (без объявления в файле заголовка), что существуют foo и bar. Напротив, объявление 1-го примера в баре позволяет любому другому классу отправлять панель сообщений экземплярам класса. Xcode также не будет отмечать ошибку для любого сообщения, чтобы bar, если @interface Class находится в заголовочном файле, который является #import другим классом.

В вопросе 2, пример 4: mySortedArray - это локальный неизменяемый массив, объявленный с локальной областью действия класса. В примере 3 mySortedArray представляет собой переменную экземпляра типа NSArray, доступную для другого класса, которая создает экземпляр класса.