Свойства ObjC и операторы C

Учитывая следующее объявление свойства:

@property NSInteger foo;

Как операторы инкремента, декремента и составного присваивания действительно работают с self.foo?

Насколько я понимаю, self.foo был просто синтаксическим сахаром для фактических методов доступа. Таким образом, self.foo не обращается напрямую к NSInteger переменной с именем foo, а вызывает либо:

- (void)setFoo:(NSInteger)foo;

or

- (NSInteger)foo;

Тем не менее, следующий набор кода прекрасен, не помечен, компилируется и возвращает точно ожидаемые результаты:

self.foo = 0;
NSLog(@"%d",self.foo); // prints 0

self.foo += 1;
NSLog(@"%d",self.foo); // prints 1

self.foo++;
NSLog(@"%d",self.foo); // prints 2

++self.foo;
NSLog(@"%d",self.foo); // prints 3

И я думаю, что, вероятно, можно с уверенностью предположить, что операторы декремента до и после исправления, а также другие 9 составных операторов будут делать именно то, что вы ожидаете, если бы вы использовали их непосредственно в переменной NSInteger.

Я просто не понимаю, ПОЧЕМУ это работает, если self.foo действительно просто синтаксический сахар для двух упомянутых выше методов.

Если я перезапишу средства доступа по умолчанию, чтобы включить операторы NSLog, чтобы я мог видеть, когда каждый из них вызывается и с какими значениями, я вижу, что сначала вызывается метод получения, а затем вызывается метод установки.

Означает ли это, что следующее:

self.foo += 1;

эффективно заменяется на это:

[self setFoo:([self foo] + 1)];

во время прекомпиляции?


РЕДАКТИРОВАТЬ: Итак, на уровне сборки есть ли разница между self.foo += 1; и self.foo = self.foo + 1;? Что, если мы не говорим о свойстве, а bar - это просто обычное целое число, есть ли на уровне сборки разница между bar += 1; и bar = bar + 1;?


person nhgrif    schedule 01.05.2014    source источник
comment
Точно. Ваше предположение верно.   -  person Avt    schedule 02.05.2014
comment
Учитывая результаты, кажется очевидным, что ваше предположение верно.   -  person rmaddy    schedule 02.05.2014
comment
Я добавил дополнение к своему вопросу, чтобы попытаться прояснить, к чему я на самом деле клоню.   -  person nhgrif    schedule 02.05.2014
comment
@nhgrif Я добавил в свой пост ответ на ваш вопрос. Пожалуйста, проверьте.   -  person Avt    schedule 02.05.2014


Ответы (1)


Точно. Ваше предположение верно. Вы можете реализовать свойство самостоятельно и добавить логирование, чтобы еще раз проверить свое предположение.

В вашем разделе @interface:

@property(nonatomic) NSInteger foo; 
     // nonatomic keyword is not really required but 
     // it is better to add it since we will implement 
     // property as nonatomic

В разделе @implementation:

- (void)setFoo:(NSInteger)foo
{
    _foo = foo; // _foo variable is implicitly generated by compiler
    NSLog(@"set foo %d", _foo);
}

- (NSInteger)foo
{
    NSLog(@"get foo %d", _foo);
    return _foo;
}

Тогда беги

self.foo = 0;
self.foo += 1;

вы должны получить в окне отладки:

set foo 0
get foo 0
set foo 1

ОБНОВИТЬ:

  • Re: "Есть ли разница между self.foo += 1; и self.foo = self.foo + 1; на уровне сборки?"

Нет. Для обоих будет называться [self setFoo:([self foo] + 1)];.

  • Re: Что, если мы не говорим о свойстве, а bar - это просто обычный int, есть ли разница между bar += 1; и bar = bar + 1; на уровне сборки?

да. Но только если отключена оптимизация времени компиляции.

bar += 1; быстрее. Он будет скомпилирован примерно так:

mov eax,dword ptr [bar]
inc eax                // difference is here!
mov dword ptr [bar],eax

И bar = bar + 1; к:

mov eax,dword ptr [bar]
add eax,1              // difference is here!
mov dword ptr [bar],eax
person Avt    schedule 01.05.2014
comment
Таким образом, составные операторы немного вводят в заблуждение относительно свойств Objective-C, если вы ожидаете, что они будут вести себя так же, как на других языках. Могу ли я предположить такую ​​же разницу в сборке для не-свойств с операторами увеличения / уменьшения? - person nhgrif; 02.05.2014
comment
@nhgrif не уверен, что правильно вас понял. Вы можете уточнить свой вопрос? - person Avt; 02.05.2014
comment
self.someVar++, someVar++, ++self.someVar, ++someVar, а также минус. - person nhgrif; 04.05.2014
comment
@nhgrif да, все они ведут себя одинаково. - person Avt; 04.05.2014