Расширение класса Objective-C
как довольно новый программист objective-c (с 4-летним опытом работы на Java), мне, похоже, трудно понять, когда использовать расширения классов. Из того, что я понял (и, пожалуйста, поправьте меня, если я ошибаюсь), основное различие между категориями и расширениями заключается в том, что расширение ожидает от вас реализации методов внутри вашей основной реализации, тогда как с категорией оно может быть в другой реализации. Также кажется, что люди используют расширения в основном для частных методы.
вот мой первый вопрос. В чем разница между использованием расширения класса для объявления частного метода и его вообще не объявлять (кажется, что он компилируется в run в обоих случаях)? (Пример 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
второй вопрос: в чем разница между объявлением ivars внутри расширения и объявлением его непосредственно внутри реализации? (Например, 3 против 4)
пример 3
@interface Class() {
NSArray *mySortedArray;
}
@end
@implementation Class
@end
Пример 4
@implementation Class
NSArray *mySortedArray;
@end
у меня есть последний вопрос о соглашениях кодирования: когда я должен поставить подчеркивание (_) перед именем переменной?
спасибо
5 ответов
методы в классе расширений
раньше не было случая, когда вам не нужно было объявлять свои частные методы. До недавнего времени вам нужно было где-то объявить свои частные методы, и большинство людей выбрали расширение класса для этого. Из Xcode 4.4 (я считаю) компилятор достаточно умен, чтобы определить, какие методы должны быть частными в этой реализации, устраняя необходимость объявлять их в другом месте.
переменные в расширения класса
что касается примеров 3 и 4, Будьте осторожны. В пределах расширения класса переменная является переменной экземпляра для этого класса (Пример 3). Пример 4 объявляет глобальную переменную (из-за того, что она следует за семантикой глобальной переменной из C). Придерживайтесь примера 3 для переменных частного экземпляра.
правила кодирования
что касается соглашения о кодировании, разработчик / команда должны решить, использовать ли подчеркивание или не. Наша команда использует m_
для частных переменных экземпляра. Яблоко в их документация предлагаю использование подчеркиваний (это стиль именования базовых переменных экземпляра для синтезированных свойств). Самое главное,чтобы быть последовательным во всем коде.
основное различие между категориями и расширениями заключается в том, что расширение ожидает от вас реализации методов внутри вашей основной реализации, тогда как с категорией оно может быть в другой реализации. Также кажется, что люди используют расширения в основном для частных методов.
правильно.
в чем разница между использованием расширения класса для объявления частного метода и не объявлять его вообще (кажется, компилировать в обоих случаях)?
возможно, просто предупреждение компилятора относительно необъявленного селектора. (Конечно, он работает нормально-метод реализован и существует.) Также обратите внимание, что объявление (известная, правильная сигнатура функции) необходимо для компилятора, чтобы испустить ABI-соответствующий, правильный двоичный код. Предположение, которое он делает о необъявленных методах (а именно, что они возвращают id
и принимать вариативные аргументы) может быть неправильным-вызов функции через указатель несовместимого типа-это неопределенное поведение.
в чем разница между объявлением ivars внутри расширения и объявлением его непосредственно внутри реализации?
в 4-м примере это глобальная переменная C, это не переменная экземпляра вашего класса.
когда я должен поставить подчеркивание ( _ ) перед именем переменной?
когда вы хотите, просто сделай это последовательно. Всегда или никогда.
в вопросе 1, Пример 2: Методы foo и bar, реализованные в классе, видны экземплярам класса. Если foo и bar не объявлены в отдельном файле заголовка, а файл реализации не доступен, другой класс не будет знать о существовании foo и bar. foo и bar являются частными методами; экземпляры класса по-прежнему будут отвечать на сообщения foo и bar. Кроме того, Xcode будет помечать предупреждение, если другой класс, который пытается отправить сообщение foo и bar, поскольку Xcode не может проверить (без объявления в заголовочном файле), что foo и bar существуют. Напротив, пример 1 объявление bar позволяет любому другому классу отправлять панель сообщений экземплярам класса. Xcode также не будет отмечать ошибку для любого сообщения, если класс @interface находится в файле заголовка, который является #import другим классом.
в вопросе 2, Пример 4: mySortedArray-это локальный неизменяемый массив, объявленный с локальной областью в классе. В mySortedArray в Примере 3, является переменной экземпляра типа NSArray доступен для другого класса, который создает экземпляр класса.