Раньше я избегал подчеркивания в именах переменных, возможно, из-за того, что я учился на Java в колледже. Поэтому, когда я определяю свойство в Objective C, я естественным образом делаю это.
// In the header
@interface Whatever
{
NSString *myStringProperty
}
@property (nonatomic, copy) NSString *myStringProperty;
// In the implementation
@synthesize myStringProperty;
Но почти в каждом примере это делается как
// In the header
@interface Whatever
{
NSString *_myStringProperty
}
@property (nonatomic, copy) NSString *myStringProperty;
// In the implementation
@synthesize myStringProperty = _myStringProperty;
Должен ли я преодолеть свое отвращение к подчеркиванию, потому что это единственный способ, которым это должно быть сделано, есть ли веские причины для того, чтобы этот стиль был предпочтительным?
Обновление: В настоящее время при автоматическом синтезе свойств вы можете опустить @synthesize, и результат будет таким же, как если бы вы использовали
@synthesize myStringProperty = _myStringProperty;
, который ясно показывает предпочтения Apple. С тех пор я научился не беспокоиться и полюбил подчеркивание.
Я всегда использую подчеркивание. Это создает четкое различие между локальными переменными и переменными экземпляра. Это также позволяет избежать предупреждений компилятора в следующей ситуации:
@interface MyClass
{
NSString *name
}
@property (nonatomic, copy) NSString *name;
- (id) initWithName:(NSString *) name;
@end
@implementation MyClass
@synthesize name;
// The following method will result in a compiler warning
// (parameter name same as ivar name)
- (id) initWithName:(NSString *) name {
if (self = [super init]) {
self.name = name;
}
return self;
}
@end
EDIT:
После того, как мне пришлось вытерпеть даунвоттинг и прочитать комментарии, позвольте мне попытаться изложить свою точку зрения:
Apple рекомендует, чтобы ivars имели то же имя, что и их свойство. Apple также рекомендует, чтобы свойства начинались со строчной буквы. И Apple также рекомендует, чтобы локальные переменные начинались со строчной буквы.
Теперь у вас есть проблема, потому что когда вы читаете кусок кода и видите, что используется переменная, вы не можете определить по соглашению об именовании, является ли эта переменная ivar или локальной переменной. Это отстой. Решение состоит в том, чтобы иметь разные соглашения об именовании для ivar и локальных переменных. Это просто здравый смысл.
То, как вы реализуете это соглашение об именовании, не имеет значения. Если вы действительно хотите, вы можете просто добавить "_WOOHAHA" к именам ivar. Мне все равно (но, возможно, другим будет все равно). Дело в том, что люди, которые знают, что они делают, решили использовать "префикс подчеркивания" для ivar. ИМХО, они приняли правильное решение, даже если их собственная компания рекомендует что-то другое. (Разработчики, о которых я говорю, - это люди, пишущие некоторые основные платформы Apple и классы .NET Framework)
В конце концов, качество кода важнее, чем следование глупому правилу, которому не следуют даже те, кто его проповедует.
Еще одно замечание по поводу показанного вами кода: никогда не используйте retain для строковых свойств. Вместо этого следует использовать copy.
Подробнее о copy/retain для свойств смотрите:
Текущая предлагаемая практика Objective-C 2.0 заключается в использовании того же имени для ivar, что и для свойства. При желании вы можете назначить другой ivar в объявлении @property, но тот факт, что по умолчанию синтезированные аксессоры для свойства будут обращаться к ivar с тем же именем, что и свойство, указывает на то, что они ожидают, что вы будете следовать этому шаблону.
Несмотря ни на что, поскольку объекты по-прежнему должны отправлять сообщения себе для доступа к свойствам, трудно запутаться, когда вы обращаетесь к свойству или когда вы напрямую обращаетесь к его поддерживающему ivar, хотя и используете доступ к свойствам через 2.0 точки делает это более возможным. Использование стандартного синтаксиса передачи сообщений делает намерение более явным, ИМО.
@interface Foo : NSObject {
NSNumber *bar;
}
@property(readwrite, retain) NSNumber * bar
@end
@implementation Foo
@synthesize bar;
-(void) baz {
NSNumber *numberOne = [NSNumber numberWithInt: 1];
//Both set the value of bar through either the your custom or the synthesized setter method
[self setBar:numberOne];
self.bar = numberOne;
//Both get the value of bar through your synthesized or your custom accessor method
NSNumber *fooBar = [self bar];
fooBar = self.bar;
//Both manipulate the bar ivar directly
bar = numberOne;
fooBar = bar;
}
@end
Apple резервирует селекторы, начинающиеся с подчеркивания, для своих собственных «частных» методов, включая свойства. Я не думаю, что они резервируют _ для имен ivar.
Лично я бы не стал использовать подчеркивание в начале любого имени переменной. Это непрозрачное соглашение. Что, если кто-то другой использует подчеркивание для локальных переменных и не использует подчеркивание для переменных экземпляра? Что, если вы случайно пропустите символ подчеркивания в методе, в котором локальный объект определен с тем же именем?
Гораздо лучше сделать ваши локальные имена отличными от ваших имен ivar. Например, в сеттере вы можете использовать newName или neWValue.
Это чисто стилистическая проблема.
Я не знаю, в каких примерах используется подчеркнутый стиль ivar. Официальные примеры Apple (например, CryptoExercise ) не содержат префикса ivars _
.
KVC-часть среды выполнения ожидает либо имя, либо _name ivar при использовании valueForKey: на объекте, когда не может найти сообщение для получения этой переменной. см. http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/SearchImplementation.html
Если среда выполнения пытается найти _name, а в документации Apple сначала упоминается _name, то для этого может быть серьезная причина. Давайте взглянем на некоторые классы SDK: UINavigationBar.h у этого класса есть символы подчеркивания перед всеми ivars, UIView тоже ... список можно продолжить. Что ж, может быть, это так с новым модным iOS SDK, и старые добрые классы NS * не делают этого ... неправильно; они также используют подчеркивание в файлах заголовков.
Apple использует подчеркивание в личных сообщениях API, а также в ivars. Я не могу понять, почему их примеры не продвигают это поведение, особенно когда среда выполнения беспокоится о том, чтобы это так называемое «соглашение об именах» было жестко закодировано в пути поиска переменных. Было бы неплохо увидеть некоторую последовательность.
Замечание: существует строгая схема именования, которой вы должны следовать, чтобы соответствовать требованиям KVC; ссылка выше поможет вам соответствовать этому, чтобы использовать эту удобную функцию среды выполнения.