Разлика между self.name и _name при използване на модерен Objective-C

Кажете, че това е в моя заглавен файл:

@interface AppDelegate : NSObject <NSApplicationDelegate>

@property (weak) IBOutlet NSSlider *slider;
- (void)doSomething;

@end

...и това е *m:

@implementation AppDelegate

- (void) doSomething {[self.slider setFloatValue:0];}

@end

Аз съм нов в Xcode и Objective C и бих искал да използвам и разбера модерните „инструменти“, представени от Apple в неговата документация, а именно ARC, или тук по-конкретно възможността за пропускане на @synthesize.

Ако съм разбрал правилно, @property (weak) IBOutlet NSSlider *slider; прави няколко неща за мен, включително:

  • създаване на екземплярна променлива, наречена _slider;
  • създаване на гетер с име slider;
  • създаване на сетер с име setSlider.

Досега работех със C++, така че виждам променливите на екземпляра като еквивалент на това, което наричам (с право, надявам се) членове на моите C++ класове, които между другото винаги наричам _member.

Разбирам, че целият смисъл на капсулирането е, че ако сте извън даден клас, трябва да използвате инструменти за достъп за достъп до тези променливи; те са частни за вас, така че няма начин да имате достъп до тях чрез _member дори и да сте опитали.

Но когато пиша своя *.m файл на моя клас, _member означава нещо. Обратно към моя пример, мисля, че self.slider и _slider са еквивалентни. Последното естествено идва на ум първо, тъй като спестява няколко знака.

Въпросът ми е: двете абсолютно еквивалентни ли са?

Знам, че това изглежда подобно на този въпрос, например, но ето няколко причини, поради които исках да си задам въпроса:

  • Не използвам @synthesize, така че наистина не съм този, който създава _slider, и се чудя дали това има значение (вярвам, че това е сравнително скорошно подобрение на ObjC и повечето отговори все още се отнасят до @synthesize);
  • изглежда, че средно повечето разговори завършват с „така че, просто използвайте self.name“, но не разбирам дали това е просто препоръка, конвенция, нещо по-важно (с въздействие, да речем, върху производителността) ;
  • по подобен начин някои казват, че трябва да използвате само _name в методи като dealloc и неговите приятели; но не ги пиша благодарение на ARC, така че това означава ли, че никога не трябва да използвам _name? Ако е така, защо?

Надявам се, че това оправдава тази публикация, извинявам се, ако съм пропуснал съществуващ отговор. Благодаря ви предварително за помощта.


person Community    schedule 29.05.2014    source източник
comment
Това твърдение е неправилно, разбирам, че целият смисъл на капсулирането е, че ако сте извън даден клас, трябва да използвате инструменти за достъп за достъп до тези променливи; те са частни за вас, така че няма начин да имате достъп до тях чрез _member дори и да сте опитали. можете да използвате оператора стрелка за достъп до променливата, напр. self->_slider. Между другото, не ви предлагам да го използвате.   -  person lucianomarisi    schedule 29.05.2014
comment
comment
Това вече е разгледано изчерпателно в Stack Overflow. Потърсете свойство [objective-c] срещу ivar или свойство [objective-c] срещу променлива на екземпляр.   -  person Rob    schedule 30.05.2014
comment
@lucianomarisi Мисля, че пропускам нещо тук… Ако опитам нещо като MyObject->_name извън изпълнението на класа MyClass за този обект, Xcode ми казва „„MyClass“ няма член с име _name“. Това не превежда ли факта, че извън изпълнението можете да получите достъп до този член само чрез свойството MyObject.name(или [MyObject name])?   -  person    schedule 30.05.2014
comment
Благодаря @MartinR и @Rob; Предполагам, че не съм използвал правилните ключови думи, съжалявам.   -  person    schedule 30.05.2014
comment
@aurelienche Тази техника за дерефериране на ivars, както намекна lucianomarisi, в днешно време се гледа с неодобрение. Би било добре да се придържате към свойствата поради редица причини (обсъдени подробно другаде). Късмет!   -  person Rob    schedule 30.05.2014
comment
@ aurelienche причината да не го виждате е, че ще трябва да декларирате променливата на екземпляра в заглавката с помощта на @public. Прочетете този въпрос stackoverflow.com/questions/5784875/   -  person lucianomarisi    schedule 30.05.2014
comment
@lucianomarisi Благодаря, това изяснява нещата!   -  person    schedule 30.05.2014


Отговори (2)


self.name = компилира до [self setName:] това е много различно от директното задаване на променливата.

Една от основните причини, поради които използването на настройката по подразбиране се различава, се занимава с наблюдение на стойността на ключ, често наричано KVO. Използването на инструмента за настройка ще уведоми наблюдателите за промени, настройката на _name директно няма.

Това не означава, че не можете сами да задействате събитията с willChangeValueForKey: и didChangeValueForKey:, но изпълнението по подразбиране ще се справи с това вместо вас. Както казвате извън класа, който има достъп до тях, трябва да използвате свойството get/set, но вътре в настройката на вашия клас променливата директно ще загуби някои известия. Сигурен съм, че има и други разлики, това е първото, за което се сещам.

Директното използване на променливата има свои случаи на употреба, като например настройка на персонализирани свойства. Мисля, че основният извод е, че синтаксисът на точката е скрито извикване на функция за получаване/задаване.

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/KeyValueObserving/Articles/KVOCompliance.html

person utahwithak    schedule 29.05.2014

При основни обстоятелства, когато използвате предварително направените инструменти за достъп, вероятно бихте могли да се разминете с използването на _slider или self.slider във вашия клас взаимозаменяемо. Те не са еквивалентни по начина, по който се компилират задължително, но може да се каже, че функционалността е еквивалентна.

По-големият проблем възниква, когато започнете да отменяте тези аксесоари. Когато тези инструменти за достъп правят нещо повече от просто "получаване" или "настройване" на променлива, като например достъп до някаква зависимостна променлива, достъпът до променливата на екземпляра директно заобикаля тази функционалност, която предоставят средствата за достъп. В тези случаи не мисля, че може да се каже, че двете са еквивалентни изобщо.

person DannyMac92    schedule 29.05.2014