Будучи новичком в Objective-C (но долгосрочном C / ++) программисте, я ищу советы / рекомендации по соглашениям о присвоении имен для переменных.
Моим личным предпочтением было бы использовать префикс для переменных экземпляра как для ясности внутри функций, так и для предотвращения затенения параметров функции. Тем не менее, я фанат свойств, которые исключают префиксы (если только вы не добавляете префиксы к именам своих свойств, что не очень хорошо работает и выглядит глупо). Точно так же я мог бы использовать соглашение «self.variable», но только если я сделаю ВСЕ свойство.
Итак, учитывая приведенный ниже код, какой стиль именования вы предпочитаете для переменных экземпляра / функции? И если вы не беспокоитесь, как вы справляетесь с отслеживанием параметров функций?
@interface GridItem : NSObject
{
CGRect _rect;
...
}
@end
-(void) initFromRect:(CGRect)rect
{
_rect = rect;
...
}
Ура!
Большинство проектов Какао используют подчеркивание как IBOutlet
префикс переменных не экземпляра и не используют префикс IBOutlet
переменных экземпляра.
Причина, по которой я не использую подчеркивания для IBOutlet
переменных экземпляра, заключается в том, что при загрузке nib-файла, если у вас есть метод установки для подключенной розетки, будет вызван этот метод установки. Однако этот механизм не использует кодирование значения ключа, поэтому IBOutlet, имя которого имеет префикс с подчеркиванием ( например _myField
), не будет установлен, если установщик не будет назван точно так же, как выход ( например set_myField:
), который является нестандартным и грубым.
Кроме того , следует помнить , что , используя свойства , как self.myProp
это не так же , как доступ к переменным экземпляра. Вы отправляете сообщение, когда используете свойство, так же, как если бы вы использовали скобочную нотацию, как [self myProp]
. Все свойства дают вам краткий синтаксис для указания как геттера, так и сеттера в одной строке, и позволяют синтезировать их реализацию; на самом деле они не закорачивают механизм отправки сообщений. Если вы хотите получить доступ к переменной экземпляра напрямую, но self
поставить перед ней префикс, вам нужно обращаться с ним self
как с указателем, как, например, self->myProp
доступ к полю в стиле C.
Наконец, никогда не используйте венгерскую нотацию при написании кода Какао и избегайте других префиксов, таких как «f» и «m_» - это пометит код как написанный кем-то, кто его не «получил», и заставит его быть замеченным подозрением другими разработчиками Какао.
В общем, следуйте рекомендациям в документе « Рекомендации по кодированию для какао» в Apple Developer Connection , и другие разработчики смогут подобрать и понять ваш код, и ваш код будет хорошо работать со всеми функциями Какао, использующими самоанализ во время выполнения.
Вот как может выглядеть класс контроллера окна, используя мои соглашения:
// EmployeeWindowController.h
#import <AppKit/NSWindowController.h>
@interface EmployeeWindowController : NSWindowController {
@private
// model object this window is presenting
Employee *_employee;
// outlets connected to views in the window
IBOutlet NSTextField *nameField;
IBOutlet NSTextField *titleField;
}
- (id)initWithEmployee:(Employee *)employee;
@property(readwrite, retain) Employee *employee;
@end
// EmployeeWindowController.m
#import "EmployeeWindowController.h"
@implementation EmployeeWindowController
@synthesize employee = _employee;
- (id)initWithEmployee:(Employee *)employee {
if (self = [super initWithWindowNibName:@"Employee"]) {
_employee = [employee retain];
}
return self;
}
- (void)dealloc {
[_employee release];
[super dealloc];
}
- (void)windowDidLoad {
// populates the window's controls, not necessary if using bindings
[nameField setStringValue:self.employee.name];
[titleField setStringValue:self.employee.title];
}
@end
Вы увидите, что я использую переменную экземпляра, которая ссылается Employee
непосредственно на метод my -init
и -dealloc
метод, в то время как я использую свойство в других методах. Как правило, это хороший шаблон со свойствами: всегда прикасайтесь к базовой переменной экземпляра для свойства в инициализаторах, в -dealloc
и в методах получения и установки для свойства.
Мне не нравится использовать подчеркивания в качестве префиксов для любых идентификаторов, потому что C и C ++ оба резервируют определенные префиксы подчеркивания для использования реализацией.
Я думаю, что использование «self.variable» безобразно.
В общем, я использую незакрашенные идентификаторы (то есть без префиксов и суффиксов) для переменных экземпляра. Если ваш класс настолько сложен, что вы не можете вспомнить переменные экземпляра, у вас проблемы. Поэтому для вашего примера я бы использовал «rect» в качестве имени переменной экземпляра, а «newRect» или «aRect» в качестве имени параметра.
Лично я следую соглашениям о присвоении имен Какао, используя верблюжий регистр для функций и переменных и заглавный верблюжий регистр для имен объектов (конечно, без начального NS).
Я считаю, что префикс типа делает код более непрозрачным для тех, кто его не писал (поскольку каждый неизменно использует разные префиксы), и в современной IDE не так уж сложно определить тип чего-либо.
Эндрю: На самом деле есть много разработчиков Cocoa, которые вообще не используют префиксы переменных экземпляра. Это также чрезвычайно распространено в мире Smalltalk (на самом деле, я бы сказал, что в Smalltalk практически не слышно использовать префиксы для переменных экземпляра).
Префиксы переменных экземпляра всегда казались мне C ++ - измом, перенесенным в Java, а затем в C #. Поскольку мир Objective-C был в значительной степени параллелен миру C ++, где, как миры Java и C #, являются его преемниками, это объяснило бы «культурную» разницу, которую вы можете увидеть в этом между различными наборами разработчиков.
С введением свойств я не вижу необходимости добавлять префикс «_» к переменным экземпляра класса. Вы можете установить простое правило (описанное в вашем заголовочном файле), что любые переменные, к которым нужно обращаться вне класса, должны быть доступны через свойство или с помощью пользовательских методов класса, чтобы воздействовать на значения. Это мне кажется намного чище, чем иметь имена с «_» на передней части. Он также правильно инкапсулирует значения, чтобы вы могли контролировать, как они изменяются.
Вы можете использовать префикс underbar на своих ivars и все же использовать имя не-underbar для ваших свойств. Для синтезированных методов доступа просто сделайте это:
@synthesize foo = _foo;
Это говорит компилятору синтезировать свойство foo с помощью the_foo ivar.
Если вы пишете свои собственные методы доступа, тогда вы просто используете в своей реализации ivar с подчеркиванием и сохраняете имя метода без подчеркивания.
Мой стиль гибридный и действительно пережиток дней PowerPlant:
Самые полезные префиксы, которые я использую, это «in» и «out» для параметров функции / метода. Это помогает вам сразу понять, для чего нужны параметры, и действительно помогает предотвратить конфликты между параметрами метода и переменными экземпляра (сколько раз вы видели, как параметр «таблица» конфликтует с переменной экземпляра с тем же именем). Например:
- (void)doSomethingWith:(id)inSomeObject error:(NSError **)outError;
Затем я использую голое имя для переменных экземпляра и имен свойств:
Затем я использую «the» в качестве префикса для локальных переменных: theTable, theURL и т. Д. Опять же, это помогает дифференцировать локальные переменные и переменные экземпляра.
Затем, следуя стилю PowerPlant, я использую несколько других префиксов: k для констант, E для перечислений, g для глобалов и s для статики.
Я использую этот стиль уже около 12 лет.
Я следую совету Криса Хэнсона в отношении префикса подчеркивания ivar, хотя признаюсь, что использую подчеркивание и для IBOutlets. Тем не менее, я недавно начал перемещать свои IBOutlet
объявления в @property
строку, согласно предложению @ mmalc . Преимущество заключается в том, что все мои ивары теперь имеют подчеркивание и называются стандартные сеттеры KVC (т.е. setNameField:
). Кроме того, имена выходов не имеют подчеркивания в Интерфейсном Разработчике.
@interface EmployeeWindowController : NSWindowController {
@private
// model object this window is presenting
Employee *_employee;
// outlets connected to views in the window
NSTextField *_nameField;
NSTextField *_titleField;
}
- (id)initWithEmployee:(Employee *)employee;
@property(readwrite, retain) Employee *employee;
@property(nonatomic, retain) IBOutlet NSTextField *nameField;
@property(nonatomic, retain) IBOutlet NSTextField *titleField;
@end
Хотя я люблю использовать префикс подчеркивания для иваров, я ненавижу писать @synthesize
строки из-за всего дублирования (это не очень СУХОЙ ). Я создал макрос, чтобы помочь сделать это и уменьшить дублирование кода. Таким образом, вместо:
@synthesize employee = _employee;
Я пишу это:
ddsynthesize(employee);
Это простой макрос, использующий вставку токена для добавления подчеркивания справа:
#define ddsynthesize(_X_) @synthesize _X_ = _##_X_
Единственным недостатком является то, что это может сбить с толку инструмент рефакторинга XCode, и он не будет переименован, если вы переименуете свойство путем рефакторинга.
Наряду с тем, что было сказано здесь, обязательно прочитайте документацию по Какао по именованию, соответствующему наблюдению ключевых значений. Строгое следование этой схеме поможет вам в долгосрочной перспективе.