Чи існує різниця між "змінною екземпляра" та "властивістю" в 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
Рядок вказує компілятору генерувати ці геттер / сеттери для вас, з допомогою змінної - члена з тим же ім'ям властивості для зберігання значення (або otherVarName
якщо ви використовуєте синтаксис в коментарях).
Поряд з цим @synthesize
ви все ще можете замінити одного з геттерів / установників, визначивши свій власний. Правила іменування для цих методів призначені setPropertyName:
для сеттера та propertyName
(або getPropertyName
, не стандартно) для геттера. Інший все одно буде створений для вас.
У вашому @property
рядку ви можете визначити ряд атрибутів у паренах для властивості, які можуть автоматизувати такі речі, як безпека потоків та управління пам'яттю. За замовчуванням властивість атомарне, тобто компілятор оберне @synthesiz
виклики get / set із відповідними блокуваннями, щоб запобігти проблемам паралельності. Ви можете вказати nonatomic
атрибут, щоб вимкнути це (наприклад, на iPhone, для якого потрібно встановити більшість властивостей за замовчуванням nonatomic
).
Існує 3 значення атрибутів, які контролюють управління пам’яттю для будь-яких @synthesized
установників. Перший - retain
це автоматичний release
перехід до старих значень властивості та retain
до нових значень. Це дуже корисно.
Другий - copy
це скопіювати будь-які передані значення, а не зберегти їх. Корисно використовувати copy
NSString, оскільки абонент може передати NSMutableString і змінити його з-під вас. copy
зробить нову копію вводу, доступ до якого ви маєте лише ви.
Третій - assign
це присвоєння прямого вказівника без виклику retain / release на старому або новому об'єкті.
Нарешті, ви також можете використовувати readonly
атрибут, щоб вимкнути сеттер для властивості.
За замовчуванням властивість readwrite підтримується змінною екземпляра, яка знову синтезується автоматично компілятором.
Змінна екземпляра - це змінна, яка існує і зберігає своє значення протягом життя об’єкта. Пам'ять, яка використовується для змінних екземпляра, виділяється при першому створенні об'єкта (через alloc) і звільняється, коли об'єкт звільняється.
Якщо не вказано інше, синтезована змінна екземпляра має те саме ім’я, що і властивість, але з префіксом підкреслення. Наприклад, для властивості, що називається firstName, синтезована змінна екземпляра буде називатися _firstName.
Раніше люди використовували властивості публічно, а ivars - для приватного використання, але, оскільки кілька років тому, ви також можете визначити властивості, @implementation
щоб використовувати їх приватно. Але я все одно використовую ivars, коли це можливо, оскільки букв для введення менше, і він працює швидше відповідно до цієї статті . Це має сенс, оскільки властивості мають бути «важкими»: доступ до них передбачається або згенерованих геттерів / сеттерів, або тих, які написані вручну.
Однак в останніх кодах від Apple ivars більше не використовуються. Я думаю , тому що це більше схоже objc
, ніж C/C++
, плюс це легше використовувати властивість з assign
, nullable
і так далі
@implementation
хоче показати схожість із Swift. Тим не менше, я також віддаю перевагу резервним змінним, щоб не витрачати виклик віртуальної функції, щоб шукати просте поле мого власного класу (і це трапляється при зверненні до властивості).