Именование экземпляра переменной переменной/метода в Objective C
В чем заключаются следующие соглашения для обозначения переменных экземпляра и аргументов метода, особенно когда аргументы метода используются для установки ivars (переменные экземпляра)?
В С++ я часто использовал префикс m_
для ivars. В С# я следовал за конвенцией о том, чтобы однозначно использовать this.
для ivars. С тех пор я тоже принял эквивалент на С++ (this->
).
В Objective C Я пробовал несколько вещей, но ни один из них не казался удовлетворительным.
Если кто-то не предложит что-то действительно приятное, я смирился с тем, что мне придется идти на компромисс (но, пожалуйста, не заставляйте меня использовать префикс the
для args!), поэтому мне интересно узнать, что большинство говорят - особенно от тех, кто некоторое время использует ObjC.
Я сделал некоторую должную осмотрительность, прежде чем опубликовать это и пару хороших ресурсов, которые я нашел где:
Они дают мне некоторые идеи, но я все еще хочу услышать, что делают другие.
[править]
Просто уточнить: конкретно, как вы отличаете ivars от аргументов метода, которые я ищу - будь то с помощью префиксов или какой-либо другой техники.
[edit 2]
Спасибо за все ответы и обсуждения. Я не закрываю это, но просто скажу, что, как я указал в своих комментариях к принятому ответу, я пошел с соглашением о префиксах init args с the
(и setter args с new
, который я все равно). Кажется, это лучший баланс сил - даже если я не увлекаюсь эстетикой.
Ответы
Ответ 1
Как вы уже отмечали, стиль Cocoa должен использовать имена аргументов метода, такие как theValue
, если имя аргумента будет конфликтовать с переменной экземпляра. Однако не должно быть много раз, что это происходит в коде стиля Objective-C 2.0. Предполагается, что вы не должны (обычно) напрямую обращаться к переменным экземпляра. В основном это происходит из-за того, что это обходит механизмы наблюдения за ключевыми значениями в Cocoa. Скорее, ожидается, что вы будете получать доступ и изменять свойства с помощью методов getter/setter. В Objective-C 2.0 легко объявить эти свойства и автоматически @synthesize
геттеры/сеттеры, поэтому нет смысла оправдывать их использование. Фактически, в 64-битных системах среда выполнения автоматически создаст переменные экземпляра для вас, избавившись от необходимости объявлять их и уменьшая желание их использовать.
Единственный раз, когда вы непосредственно обращаетесь к переменным экземпляра, находится в методах -init
и -dealloc
:
@interface MyObject : NSObject
{
id ivar;
}
@property (retain,readwrite) id ivar; //or whatever retain/copy/assign and read/readwrite makes sense
@end
@implementation MyObject
@synthesize ivar;
- (id)initWithIvar:(id)theIvar {
if(self = [super init]) {
ivar = theIvar;
}
return self;
}
- (void)dealloc {
[ivar release];
}
Причина, по которой ivar следует использовать непосредственно в этих случаях, является причиной того, что геттер/сеттер может иметь побочные эффекты, которые зависят от полностью инициализированного экземпляра, что делает их опасными в -init
и -dealloc
, где состояние объекта полностью инициализируется. Во всех остальных случаях вы должны использовать self.ivar
(или [self ivar]
и [self setIvar:newValue]
).
Казалось бы, что методы, отличные от -initWithXX
, не должны иметь конфликт имен. Если они это сделают, не должны ли они быть реорганизованы, чтобы не иметь этот параметр или для класса не иметь переменную экземпляра?
Это оставляет только методы -initWithXX
, где вы часто находите конфликт между аргументами и ivars. В этом случае вы можете использовать любой из указанных вами подходов, если вы действительно не можете выдержать стиль Cocoa. Префикс с _
работает и относительно распространен (я полагаю, что настройки @synthesize
'd seters и getters будут автоматически делать правильные вещи в этом случае, но вам может потребоваться явно установить _ivar
в качестве поддержки).
Ответ 2
Здесь Apple делает это.
Ответ 3
Чтобы завершить все известные Objective-C стилегиды здесь, это версия Google. Они делают это, чтобы добавить символ подчеркивания после члена varname. Например BOOL isActive_;
.
Поэтому сделайте выбор и придерживайтесь его. Я также предпочитаю префикс "_" для своих приложений.
Ответ 4
Пример кода, созданного Apple, обычно использует префикс "_". Я думаю, что я также видел некоторые, используя mFoo
или m_foo
. Некоторые вообще не беспокоятся о префиксах и просто используют нормальное имя, однако это путает позже. В общем случае при определении параметров метода соглашение об именах заключается в использовании префикса "a", "an", "the" или "new". Например:
@interface Foo : NSObject {
id _bar;
}
@property (nonatomic, retain) id bar;
- (id) initWithBar:(id)aBar;
@end
@implementation Foo
@synthesize bar = _bar;
- (id) initWithBar:(id)aBar {
self = [super init];
if(self != nil) {
_bar = aBar;
}
return self;
}
@end
Я нахожу, что это соглашение работает очень хорошо. Раньше я не беспокоился о префиксе, но иногда это приводило в замешательство. Использование префикса ясно указывает, что это переменная экземпляра. Соглашение @synthesize bar = _bar
используется Apple в их образце кода (iPhone).
Обычно переменная экземпляра обычно не используется, поэтому, если вы находите, что префикс "_" раздражает, это не имеет значения, потому что вы использовали бы [self bar]
(или self.bar
, если вы входите в этот тип вещь) в любом случае.
Ответ 5
Obj-C не определяет "стиль" так же строго, как и многие другие языки, это может быть хорошей или, скорее, плохой, но это означает, что вы сами можете найти хороший стиль кодирования большую часть времени.
Вы также можете получить доступ к переменным в Obj-C через self. Поэтому, если у вас есть тест переменной экземпляра, вы можете получить к нему доступ через self- > test, это законно и всегда будет работать. Однако это не красиво в глазах большинства программистов Obj-C. Это отдает "секрет", что объекты на самом деле являются просто структурами (точнее, объектные ссылки являются указателями на структуры), а экземпляры vars на самом деле являются членами структуры. Не то чтобы это действительно секретно, но программисты Obj-C, похоже, предпочитают "скрывать" этот факт в своем коде.
Использование подчеркивания "_" в названии - очень плохая идея. Кто-то здесь указал, что Apple резервирует знак для своего кода, но на самом деле GCC уже резервирует знак подчеркивания для имен символов. Точнее, уже в стандарте ANSI-C указано, что переменные, начинающиеся с двух подчеркиваний или одного подчеркивания и буквы верхнего регистра, зарезервированы для внутреннего использования компилятора. Таким образом, использование одного подчеркивания теоретически справедливо, но случайно запустим имя с буквой в верхнем регистре и оно станет недействительным.
До сих пор я пытался использовать префикс my, myName вместо имени и использовать префикс self, selfName вместо имени; сначала выглядит как-то странно, но в огромном фрагменте кода он не выглядит слишком плохим. По крайней мере, сразу попадает в глаза как "разные". Я также просто попробовал один "i", iName вместо имени (или вместо имени), но я не был очень доволен этим решением.
Я никогда не терял время, думая о параметрах метода. Потому что это не имеет большого значения. Это переменные, как и любые другие переменные, если они не объявлены постоянными. Они могут быть даже повторно использованы для других целей в рамках метода, потому что это не повлияет на вызывающего. Например.
- (NSImage *)loadImage:(int)imageNumber
{
NSImage * res;
// Some code that assigns a value to res
// ...
// Re-use imageNumber for a different purpose
for (imageNumber = 0; ...; ...) {
// Some code
}
return res;
}
Я не вижу проблем с этим кодом. Почему мне нужно объявить вторую переменную стека для этого, если имя все еще имеет смысл (если я не повторяю образы по номеру в цикле for, это имя не имеет никакого смысла, в этом случае я бы использовал другая переменная для него - компилятор может фактически зарезервировать только один int для стека для обоих).