Присвоение свойства Objective-C возвращает присвоенное значение?

Скажите, что у меня есть следующее:

@interface MyClass : NSObject { NSString* _foobar; }
@property (nonatomic, retain) NSString* foobar;
@end

@implementation MyClass
@dynamic foobar;
- (void) setFoobar:(NSString*)fbSet; { [_foobar release]; _foobar = [fbSet retain]; }
- (NSString*) foobar; { return _foobar; }
@end

Затем:

MyClass* mcInst = [[[MyClass alloc] init] autorelease];
NSLog(@"I set 'foobar' to '%@'", (mcInst.foobar = @"BAZ!"));

Рассмотрение возвращаемого значения -[MyClass setFoobar:], можно было бы предположить здесь, что эта строка распечатает I set 'foobar' to '', потому что присвоение, кажется, ничего не возвращает.

Однако - к счастью - это присвоение действует как ожидалось, и печать кода I set 'foobar' to 'BAZ!'. К сожалению, это чувствует себя подобно противоречию, потому что возвращаемое значение вызванного метода set противоречит тому, что присвоение возвращает значение, присвоенное ему. Сначала я изобразил это mcInst.foobar = @"BAZ!"; выполняет два вызова вместо этого блок: сначала метод set и затем метод считывания для сбора возвращаемого значения. Однако оснащая методы установщика и методы получателя с NSLog вызовы доказывают, что это не имеет место.

6
задан Lebyrt 9 May 2014 в 08:38
поделиться

4 ответа

Быстрое обобщение:

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

(mcInst.foobar = @"BAZ!")

на самом деле является @"BAZ!", а не mcInst.foobar.

Более подробная информация доступна ниже, но, возможно, поможет рассмотреть следующую модификацию вашего метода setFoobar:

- (void) setFoobar:(NSString*)fbSet
{
    [_foobar release];
    _foobar = [[NSString stringWithFormat:@"HELLO_%@", fbSet] retain];
}

При наличии этого кода, значение свойства foobar изменяется во время его установки, , но в вашей строке кода все равно будет отображаться значение 'BAZ!'.

Подробности:

Как указывает newacct, ваш код NSLog работает, так как вы используете оператор присваивания (=), который имеет очень специфическое поведение в языке Си (на котором основана Objective-C)

В языке Си вы можете сделать следующее:

x = y = z = 42;

и все переменные, x, y и z будут содержать значение 42.

Компилятор обрабатывает это поведение, используя временную переменную(*). По сути, то, что происходит за кулисами, выглядит примерно так:

tempVar = 42;
z = tempVar;
y = tempVar;
x = tempVar;

В той же строке кода можно сделать следующее:

SomeFunction(x = 42);

эта строка кода скопирует значение 42 в x, а затем вызовет SomeFunction с аргументом 42. За сценами это выглядит следующим образом:

tempVar = 42;
x = tempVar;
SomeFunction(tempVar);

Теперь, в Objective-C, ваша строка протоколирования обрабатывается следующим образом:

tempVar = @"BAZ!";
[mcInst setFooBar:tempVar];
NSLog(@"I set 'foobar' to '%@'", tempVar);

(*) обратите внимание, что использование "временной переменной", которую я описываю, предназначено для иллюстрации концепции, и может на самом деле не отражать то, что любой данный компилятор на самом деле делает под капотом. Такая реализация зависит от программистов, которые пишут компилятор, и каждый из них может делать что-то свое. Конечный результат, однако, один и тот же.

9
ответ дан 10 December 2019 в 00:38
поделиться

в языке С, присвоение - это выражение, которое оценивает присвоенное значение

.
0
ответ дан 10 December 2019 в 00:38
поделиться

Я нахожу плагин m2eclips e более полезным. Это обеспечивает хорошие инструменты, такие как редактор POM и создание проекта Maven в Eclipse.

-121--636036-

Если точно известно, сколько вкладок префиксирует каждая строка (как указано), можно использовать простой query-replace-regex для замены «^\t\t\t ...\t» на «» .

-121--1640905-

Это связано с путем работы оператора назначения C. Как описано в стандарте ANSI C:

"Оператор назначения сохраняет значение в объекте, обозначенном левый операнд. Выражение назначения имеет значение слева операнд после назначения "...

Выражение назначения mcInst.foobar = @" BAZ! ". Мне кажется, имеет смысл, что даже если назначение работает путем вызова метода на mcInst поведение то же, что и с C. Значение выражения назначения является левым операндом после назначения ( @ «BAZ!» ), поэтому это значение передается функции NSLog.

Это то же поведение, которое позволяет написать инициализатор в стиле , если (self = [super init]) .

P.S. Справедливо задать вопрос, почему компилятор вызывает установщик свойства при присвоении ему значения и не вызывает получателя при последующем использовании значения mcInst.foobar . Я бы сказал, что просто предполагается, что getter вернет то же значение, которое только что было присвоено свойству, и поэтому getter не называется.

0
ответ дан 10 December 2019 в 00:38
поделиться

Нет необходимости вызывать геттера - ему присваивается значение прямо на этой же линии. Можно считать, что оно расширяется до [mcInst setFoobar:@"BAZ!"], @"BAZ!".

1
ответ дан 10 December 2019 в 00:38
поделиться