Как вы называете значения экземпляра/параметра?
-
08-06-2019 - |
Вопрос
Будучи новичком в Objective-C (но давним программистом на C/++), я ищу советы/рекомендации по соглашениям об именах для переменных.
Лично я предпочитаю использовать префикс для переменных экземпляра как для ясности внутри функций, так и для предотвращения затенения параметров функций.Однако я сторонник свойств, которые исключают префиксы (если только вы не добавляете префиксы к именам свойств, что работает не слишком хорошо и выглядит глупо).Точно так же я мог бы использовать соглашение «self.variable», но только если я сделаю ВСЕ свойством.
Итак, учитывая приведенный ниже код, какой стиль именования для переменных экземпляра/функции вы предпочитаете?И если вас не затруднит, как вы справляетесь с затенением параметров функции?
@interface GridItem : NSObject
{
CGRect _rect;
...
}
@end
-(void) initFromRect:(CGRect)rect
{
_rect = rect;
...
}
Ваше здоровье!
Решение
Большинство проектов Cocoa используют нижнюю полосу как необязательный элемент.IBOutlet
префикс переменной экземпляра и не используйте префикс для IBOutlet
переменные экземпляра.
Причина, по которой я не использую подчеркивания IBOutlet
Переменные экземпляра заключаются в том, что при загрузке файла пера, если у вас есть метод установки для подключенной розетки, этот метод установки будет вызываться. Однако этот механизм делает нет используйте кодирование «ключ-значение», поэтому IBOutlet, имя которого начинается с подчеркивания (например _myField
) воля нет быть установлен, если установщик не назван точно так же, как выход (например set_myField:
), что является нестандартным и брутто.
Также имейте в виду, что использование таких свойств, как self.myProp
является нет то же самое, что и доступ к переменным экземпляра.Ты отправка сообщения когда вы используете свойство, точно так же, как если бы вы использовали обозначение скобок, например [self myProp]
.Все, что делают свойства, — это дают вам краткий синтаксис для указания как геттера, так и сеттера в одной строке, и позволяют синтезировать их реализацию;на самом деле они не замыкают механизм отправки сообщений.Если вы хотите напрямую получить доступ к переменной экземпляра, но присвоить ей префикс self
тебе нужно лечить self
как указатель, например self->myProp
что на самом деле является доступом к полю в стиле C.
Наконец, никогда не используйте венгерскую нотацию при написании кода Cocoa и избегайте других префиксов, таких как «f» и «m_» — они будут отмечать код как написанный кем-то, кто «не понимает», и это приведет к тому, что он будет может вызвать подозрение у других разработчиков Cocoa.
В общем, следуйте советам в Рекомендации по кодированию для какао документ на Связь с разработчиками Apple, и другие разработчики смогут уловить и понять ваш код, и ваш код будет хорошо работать со всеми функциями Cocoa, использующими самоанализ во время выполнения.
Вот как может выглядеть класс оконного контроллера, если использовать мои соглашения:
// 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
прямо в моем -init
и -dealloc
метод, в то время как я использую это свойство в других методах.Обычно это хороший шаблон со свойствами:Прикасайтесь только к базовой переменной экземпляра свойства в инициализаторах, в -dealloc
, а также в методах получения и установки свойства.
Другие советы
Я следую совету Криса Хэнсона относительно префикса подчеркивания ivar, хотя признаю, что использую подчеркивание и для IBOutlets.Однако недавно я начал перемещать свой IBOutlet
заявления для @property
линия, согласно предложение @mmalc.Преимущество в том, что все мои ivar теперь имеют подчеркивание и вызываются стандартные установщики 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
Вы можете использовать префикс подчеркивания в своих ivars и по-прежнему использовать имя без подчеркивания для своих свойств.Для синтезированных средств доступа просто сделайте следующее:
@synthesize foo = _foo;
Это указывает компилятору синтезировать свойство foo, используя ivar_foo.
Если вы пишете свои собственные методы доступа, вы просто используете ivar с подчеркиванием в своей реализации и сохраняете имя метода без подчеркивания.
Лично я следую соглашениям об именах Cocoa, используя верблюжий регистр для функций и переменных и записывая верблюжьи буквы для имен объектов (конечно, без начального NS).
Я считаю, что префиксы типов делают код более непрозрачным для тех, кто его не писал (поскольку все неизменно используют разные префиксы), а в современной IDE не так уж и сложно определить тип чего-либо.
С введением свойств я не вижу необходимости добавлять префикс «_» к переменным экземпляра класса.Вы можете установить простое правило (описанное в заголовочном файле), согласно которому доступ к любым переменным, внешним по отношению к классу, должен осуществляться через свойство или с помощью пользовательских методов класса для воздействия на значения.Мне кажется, это намного чище, чем имена с «_» впереди.Он также правильно инкапсулирует значения, чтобы вы могли контролировать их изменение.
Мне не нравится использовать символы подчеркивания в качестве префиксов для любых идентификаторов, поскольку C и C++ резервируют определенные префиксы подчеркивания для использования реализацией.
Я думаю, что использовать «self.variable» некрасиво.
Обычно я использую простые идентификаторы (то есть без префиксов и суффиксов) для переменных экземпляра.Если ваш класс настолько сложен, что вы не можете запомнить переменные экземпляра, у вас проблемы.Итак, для вашего примера я бы использовал «rect» в качестве имени переменной экземпляра и «newRect» или «aRect» в качестве имени параметра.
Андрей:На самом деле существует множество разработчиков Cocoa, которые вообще не используют префиксы переменных экземпляра.Это также чрезвычайно распространено в мире Smalltalk (на самом деле, я бы сказал, что в Smalltalk почти неслыханно использовать префиксы для переменных экземпляра).
Префиксы переменных экземпляра всегда казались мне стилем C++, который был перенесен в Java, а затем и в C#.Поскольку мир Objective-C во многом был параллелен миру C++, а миры Java и C# являются его преемниками, это объясняет «культурную» разницу, которую вы можете увидеть в этом между разными группами разработчиков.
Мой стиль гибридный и на самом деле пережиток времен PowerPlant:
Наиболее полезные префиксы, которые я использую, — это «in» и «out» для параметров функции/метода.Это поможет вам сразу понять, для чего нужны параметры, и действительно помогает предотвратить конфликты между параметрами метода и переменными экземпляра (сколько раз вы видели конфликт параметра «таблица» с переменной экземпляра с тем же именем).Например.:
- (void)doSomethingWith:(id)inSomeObject error:(NSError **)outError;
Затем я использую чистое имя для переменных экземпляра и имен свойств:
Затем я использую «the» в качестве префикса для локальных переменных:theTable, theURL и т. д.Опять же, это помогает различать локальные переменные и переменные экземпляра.
Затем, следуя стилю PowerPlant, я использую несколько других префиксов:k для констант, E для перечислений, g для глобальных переменных и s для статики.
Я использую этот стиль уже около 12 лет.
Хотя мне нравится использовать префикс подчеркивания для иваров, я ненавижу писать @synthesize
строк из-за всего дублирования (это не очень СУХОЙ).Я создал макрос, который поможет сделать это и уменьшить дублирование кода.Таким образом, вместо:
@synthesize employee = _employee;
Я пишу это:
ddsynthesize(employee);
Это простой макрос, использующий вставку токенов для добавления подчеркивания справа:
#define ddsynthesize(_X_) @synthesize _X_ = _##_X_
Единственным недостатком является то, что это запутает инструмент рефакторинга Xcode и не будет переименовано, если вы переименуете свойство путем рефакторинга.
Помимо того, что было сказано здесь, обязательно прочитайте документацию Cocoa по именованию, совместимому с Key Value Observing.Строгое следование этому шаблону очень поможет вам в долгосрочной перспективе.