именование переменных экземпляра / метода в Objective C - PullRequest
15 голосов
/ 15 февраля 2009

Какие здесь соблюдаются соглашения для именования переменных экземпляра и аргументов метода, особенно когда аргументы метода используются для установки ivars (переменных экземпляра)?

В C ++ я часто использовал префикс m_ для иваров. В C # я следовал соглашению об устранении двусмысленности, просто используя this. для иваров. С тех пор я принял аналог в C ++ (this->).

В Задаче C я попробовал несколько вещей, но ни одна из них не показалась мне удовлетворительной.

Если кто-то не предлагает что-то действительно хорошее, я смирился с тем, что мне придется идти на компромисс (но, пожалуйста, не заставляйте меня использовать префикс the для аргументов!), Поэтому мне интересно узнать, что большинство говорят - особенно от тех, кто какое-то время использовал ObjC.

Я провел некоторую проверку, прежде чем опубликовать это, и пару хороших ресурсов, которые я нашел где:

Они дают мне некоторые идеи, но я все еще хочу услышать, что делают другие.

[править] Просто чтобы уточнить: именно то, как вы отличаете ivars от аргументов метода, я ищу - будь то с помощью префиксов или какой-то другой техники.

[править 2] Спасибо за все ответы и обсуждения. Я не закрываю это, но просто скажу, что, как я указал в моих комментариях к принятому ответу, я согласился с префиксом аргументов init с the (и аргументами setter с new, который я делал все равно). Это, кажется, лучший баланс сил - даже если я сам не увлекаюсь эстетикой.

Ответы [ 5 ]

17 голосов
/ 15 февраля 2009

Как вы заметили, стиль Какао заключается в использовании имен аргументов метода, таких как theValue, если имя аргумента будет конфликтовать с переменной экземпляра. Однако не должно быть много раз, чтобы это встречалось в коде стиля Objective-C 2.0. Предполагается, что вы не должны (обычно) обращаться к переменным экземпляра напрямую. Главным образом это происходит потому, что это позволяет обойти механизм наблюдения ключевых значений в какао. Скорее всего, вы ожидаете, что вы будете обращаться к свойствам и изменять их с помощью методов получения / установки. В 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];
}

Причина, по которой ивар должен использоваться непосредственно в этих случаях, заключается в том, что геттер / установщик могут иметь побочные эффекты, которые зависят от полностью инициализированного экземпляра, что делает их опасными в -init и -dealloc, где состояние объекта полностью инициализирован. Во всех остальных случаях вы должны использовать self.ivar (или [self ivar] и [self setIvar:newValue]).

Может показаться, что методы, отличные от -initWithXX, не должны иметь конфликта имен. Если это так, разве они не должны подвергаться рефакторингу, чтобы не иметь этого параметра, или чтобы класс не имел переменной экземпляра?

Это оставляет только методы -initWithXX, в которых вы часто находите конфликт между аргументами и ivars. В этом случае вы можете использовать любой из упомянутых вами подходов, если вы действительно не можете выдержать стиль Какао. Префикс к _ работает и является относительно распространенным (я полагаю, что установщики и получатели @synthesize автоматически сделают правильную вещь в этом случае, но вам, возможно, придется явно установить _ivar в качестве поддержки).

2 голосов
/ 16 февраля 2009

Для завершения всех известных стилевых указаний Objective-C здесь - версия Google. Что они делают, так это добавляют подчеркивание после имени элемента. Например BOOL isActive_;.
Поэтому сделайте выбор и придерживайтесь его. Я также предпочитаю префикс "_" для своих приложений.

2 голосов
/ 15 февраля 2009
1 голос
/ 09 декабря 2009

Obj-C не определяет "стиль" так строго, как во многих других языках, это может быть хорошо или скорее плохо, но это означает, что вы в большинстве случаев самостоятельно выбираете хороший стиль кодирования.

Вы также можете обращаться к переменным в Obj-C через себя. Так что если у вас есть экземпляр переменной test, вы можете получить к нему доступ через self-> test, это законно и всегда будет работать. Это не красиво в глазах большинства программистов на Obj-C. Он раскрывает «секрет», что объекты на самом деле являются просто структурами (точнее, ссылки на объекты являются указателями на структуры), а переменные экземпляров фактически являются членами структуры. Не то чтобы это действительно секрет, но программисты Obj-C предпочитают «скрывать» этот факт в своем коде.

Использование подчеркивания "_" в названии - очень плохая идея. Кто-то здесь отметил, что Apple резервирует подчеркивание для своего кода, но на самом деле GCC уже резервирует подчеркивание для имен символов. Точнее, уже стандарт ANSI-C гласит, что переменные, начинающиеся с двух подчеркиваний или одного подчеркивания и заглавной буквы, зарезервированы для внутреннего использования компилятором. Таким образом, использование одного подчеркивания теоретически допустимо, но случайно начинайте имя с заглавной буквы, и оно становится недействительным.

До сих пор я пытался использовать префикс my, myName вместо имени и использовать префикс self, selfName вместо имени; Поначалу выглядит как-то странно, но не выглядит слишком плохо в огромном куске кода. По крайней мере, сразу бросается в глаза, как "разные". Я также попытался использовать только одно i, iName вместо name (или iname вместо name), но меня это решение не очень удовлетворило.

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

- (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 в стеке для обоих).

1 голос
/ 15 февраля 2009

Пример кода, созданного 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, если вы находитесь в такого рода вещь) в любом случае.

...