6

私は次のものを持っているとしましょう:

@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!'. 残念ながら、呼び出されたセッターの戻り値は、割り当てがそれに割り当てられた値を返すという事実に反するため、これは矛盾しているように感じます。最初mcInst.foobar = @"BAZ!";は、ブロックの代わりに 2 つの呼び出しを行っていると考えました。最初はセッター、次に戻り値を収集するためのゲッターです。ただし、setter メソッドと getter メソッドをNSLog呼び出しでインストルメント化すると、そうではないことが証明されます。

4

4 に答える 4

9

簡単な要約:

ここでの簡単な答えは、矛盾がないということです。式の結果は次のとおりです。

(mcInst.foobar = @"BAZ!")

実際@"BAZ!"ではありません mcInst.foobar

以下に詳細を示しますが、setFoobarメソッドに次の変更を加えることを検討すると役立つ場合があります。

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

このコードを配置すると、foobar設定中にプロパティの値が変更されますが、コード行には引き続き値「BAZ!」が表示されます。.

詳細:

newacctで指摘されているように、代入演算子 (=) を使用しているため、NSLog コードが機能します。これは、C 言語 (Objective-C が基づいている) で非常に特殊な動作をします。

C では、次のことができます。

x = y = z = 42;

すべての変数 、xyおよびzは値 42 を保持します。

コンパイラは、一時変数 (*) を使用してこの動作を処理します。基本的に、舞台裏で起こっていることは次のようになります。

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

同じように、次のことができます。

SomeFunction(x = 42);

このコード行は、42 の値を x にコピーし、引数 42 で呼び出しますSomeFunction。裏では、次のようになります。

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

現在、Objective-C では、ログ行は次のように処理されます。

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

(*) ここで説明する「temporaray 変数」の使用法は、概念を説明するためのものであり、特定のコンパイラが内部で実際に行っていることを実際に反映していない可能性があることに注意してください。この種の実装の詳細は、コンパイラを作成するプログラマに任されており、それぞれが異なることを行う可能性があります。ただし、最終結果は同じです。

于 2010-01-13T21:54:47.083 に答える
1

ゲッターを呼び出す必要はありません — 同じ行に値が割り当てられています。に展開すると考えることができます[mcInst setFoobar:@"BAZ!"], @"BAZ!"

于 2010-01-13T23:40:35.543 に答える
0

これは、C 代入演算子の動作方法によるものです。ANSI C 標準で説明されているように:

「代入演算子は、左オペランドで指定されたオブジェクトに値を格納します。代入式は、代入後に左オペランドの値を持ちます...」

あなたの代入式はmcInst.foobar = @"BAZ!". mcInst でメソッドを呼び出すことによって代入が機能するにもかかわらず、C と同じ動作をすることは私には理にかなっているように思えます。代入式の値は、代入 ( @"BAZ!") の後の左オペランドであるため、この値は NSLog関数。

これは、 のスタイルでイニシャライザを記述できるのと同じ動作ですif (self = [super init])

mcInst.foobarPSなぜコンパイラがプロパティに値を代入するときにセッターを呼び出し、後で値を使用するときにゲッターを呼び出さないのかを尋ねるのは公正な質問です。ゲッターがプロパティに割り当てられたばかりの同じ値を返すと単純に想定しているため、ゲッターは呼び出されません。

于 2010-01-13T23:30:56.917 に答える