Префикс имен свойств с подчеркиванием в Objective C [дубликат]

Раньше я избегал подчеркивания в именах переменных, возможно, из-за того, что я учился на 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. С тех пор я научился не беспокоиться и полюбил подчеркивание.

54
задан Michael Behan 16 April 2014 в 20:16
поделиться

5 ответов

Я всегда использую подчеркивание. Это создает четкое различие между локальными переменными и переменными экземпляра. Это также позволяет избежать предупреждений компилятора в следующей ситуации:

@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 для свойств смотрите:

Свойство NSString: copy или retain?

47
ответ дан 7 November 2019 в 07:56
поделиться

Текущая предлагаемая практика 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 
18
ответ дан 7 November 2019 в 07:56
поделиться

Apple резервирует селекторы, начинающиеся с подчеркивания, для своих собственных «частных» методов, включая свойства. Я не думаю, что они резервируют _ для имен ivar.

Лично я бы не стал использовать подчеркивание в начале любого имени переменной. Это непрозрачное соглашение. Что, если кто-то другой использует подчеркивание для локальных переменных и не использует подчеркивание для переменных экземпляра? Что, если вы случайно пропустите символ подчеркивания в методе, в котором локальный объект определен с тем же именем?

Гораздо лучше сделать ваши локальные имена отличными от ваших имен ivar. Например, в сеттере вы можете использовать newName или neWValue.

6
ответ дан 7 November 2019 в 07:56
поделиться

Это чисто стилистическая проблема.

Я не знаю, в каких примерах используется подчеркнутый стиль ivar. Официальные примеры Apple (например, CryptoExercise ) не содержат префикса ivars _ .

3
ответ дан 7 November 2019 в 07:56
поделиться

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; ссылка выше поможет вам соответствовать этому, чтобы использовать эту удобную функцию среды выполнения.

1
ответ дан 7 November 2019 в 07:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: