Есть ли разница между "переменной экземпляра" и "свойством" в Objective-c?
Я не очень уверен в этом. Я думаю, что "свойство" - это переменная экземпляра, которая имеет методы доступа, но я могу ошибаться.
Есть ли разница между "переменной экземпляра" и "свойством" в Objective-c?
Я не очень уверен в этом. Я думаю, что "свойство" - это переменная экземпляра, которая имеет методы доступа, но я могу ошибаться.
Свойство является более абстрактным понятием. Переменная экземпляра - это буквально только слот для хранения данных, такой как слот в структуре. Обычно другие объекты никогда не должны обращаться к ним напрямую. С другой стороны, свойство является атрибутом вашего объекта, к которому можно получить доступ (он звучит неопределенно и он должен). Обычно свойство возвращает или задает переменную экземпляра, но может использовать данные из нескольких или вообще ничего. Например:
@interface Person : NSObject {
NSString *name;
}
@property(copy) NSString *name;
@property(copy) NSString *firstName;
@property(copy) NSString *lastName;
@end
@implementation Person
@synthesize name;
- (NSString *)firstName {
[[name componentsSeparatedByString:@" "] objectAtIndex:0];
}
- (NSString *)lastName {
[[name componentsSeparatedByString:@" "] lastObject];
}
- (NSString *)setFirstName:(NSString *)newName {
NSArray *nameArray = [name componentsSeparatedByString:@" "];
NSArray *newNameArray [[NSArray arrayWithObjects:newName, nil] arrayByAddingObjectsFromArray:[nameArray subarrayWithRange:NSMakeRange(1, [nameArray size]-1)]];
self.name = [newNameArray componentsJoinedByString:@" "];
}
- (NSString *)setLastName:(NSString *)newName {
NSArray *nameArray = [name componentsSeparatedByString:@" "];
NSArray *newNameArray [[nameArray subarrayWithRange:NSMakeRange(0, [nameArray size]-2)] arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:newName, nil]];
self.name = [newNameArray componentsJoinedByString:@" "];
}
@end
(Примечание: приведенный выше код ошибочен в том смысле, что он предполагает, что имя уже существует и имеет как минимум два компонента (например, "Билл Гейтс", а не только "Гейтс" ). Я чувствовал, что фиксация этих предположений сделает фактическую точку кода менее ясны, поэтому я просто указываю на это, поэтому никто невинно повторяет эти ошибки.)
Свойство - это дружественный способ реализации getter/setter для некоторого значения, с дополнительными полезными функциями и синтаксисом. Свойству может быть присвоена переменная экземпляра, но вы также можете определить геттер/сеттер, чтобы сделать что-то более динамичное, например. вы можете определить свойство lowerCase для строки, которая динамически создает результат, а не возвращает значение некоторой переменной-члена.
Вот пример:
// === In your .h ===
@interface MyObject {
NSString *propertyName;
}
// ...
@property (nonatomic, retain) NSString *propertyName;
// === In your .m @implementation ===
@synthesize propertyName /* = otherVarName */;
Строка @property
определяет свойство propertyName
типа NSString *
. Это можно получить/установить, используя следующий синтаксис:
myObject.propertyName = @"Hello World!";
NSLog("Value: %@", myObject.propertyName);
Когда вы назначаете или читаете из myObject.propertyName
, вы действительно вызываете методы setter/getter на объекте.
Строка @synthesize
сообщает компилятору генерировать эти getter/seters для вас, используя переменную-член с тем же именем свойства, чтобы сохранить значение (или otherVarName
, если вы используете синтаксис в комментариях).
Наряду с @synthesize
вы все равно можете переопределить один из элементов getter/setters, указав свой собственный. Соглашение об именах для этих методов setPropertyName:
для сеттера и propertyName
(или getPropertyName
, а не стандартное) для получателя. Другой будет создан для вас.
В вашей строке @property
вы можете определить несколько атрибутов в parens для свойства, которое может автоматизировать такие функции, как управление потоками и управление памятью. По умолчанию свойство атомарное означает, что компилятор будет обертывать @synthesiz
ed get/set calls с соответствующими блокировками для предотвращения проблем concurrency. Вы можете указать атрибут nonatomic
, чтобы отключить его (например, на iPhone, который вы хотите по умолчанию для большинства свойств, nonatomic
).
Существует 3 значения атрибута, которые управляют управлением памятью для любых установщиков @synthesized
. Первая - это retain
, которая автоматически отправит release
к старым значениям свойства и retain
к новым значениям. Это очень полезно.
Второй copy
, который сделает копию любых значений, переданных, а не сохраняя их. Рекомендуется использовать copy
для NSString, потому что вызывающий может передать NSMutableString и изменить его из-под вас. copy
создаст новую копию ввода, к которой у вас есть доступ.
Третий assign
, который присваивает прямой указатель без вызова сохранения/освобождения на старом или новом объекте.
Наконец, вы также можете использовать атрибут readonly
, чтобы отключить средство настройки для этого свойства.
Я использую свойства для части интерфейса - где объект взаимодействует с другими объектами и переменные экземпляра - это вещи, которые вам нужны внутри вашего класса - никто, но вы должны видеть и манипулировать ими.
По умолчанию свойство readwrite будет поддерживаться переменной экземпляра, которая будет автоматически синтезироваться компилятором.
Переменная экземпляра - это переменная, которая существует и сохраняет свое значение для жизни объекта. Память, используемая для переменных экземпляра, выделяется, когда объект сначала создается (через alloc) и освобождается, когда объект освобождается.
Если вы не указали иначе, переменная синтезированного экземпляра имеет то же имя, что и свойство, но с префиксом подчеркивания. Например, для свойства, называемого firstName, синтезированная переменная экземпляра будет называться _firstName.
Раньше люди публично использовали свойства и ivars для частного использования, но несколько лет назад вы также можете определить свойства в @implementation
, чтобы использовать их конфиденциально. Но по-прежнему я использую ivars, так как набирается меньше букв, и он работает быстрее в соответствии с этой статьей. Это имеет смысл, поскольку свойства являются средними, чтобы быть "тяжелыми": к ним следует обращаться либо из сгенерированных геттеров/сеттеров, либо из написанных вручную.
Однако, в последних кодах от Apple, ivars больше не используются. Я думаю, потому что это больше похоже на objc
, а не на C/C++
, плюс его проще использовать свойства с assign
, nullable
и т.д.