سؤال

أقول التالية:

@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!"; هو إجراء مكالمتين بدلا كتلة:أول واضع ثم حاصل جمع قيمة الإرجاع.ومع ذلك ، instrumenting واضع جالبة الطرق مع NSLog المكالمات يثبت هذا ليس هو الحال.

هل كانت مفيدة؟

المحلول

ملخص سريع:

الجواب السريع هنا هو أنه لا يوجد تناقض, لأن نتيجة التعبير:

(mcInst.foobar = @"BAZ!")

هو في الواقع @"BAZ!", ، لا mcInst.foobar.

المزيد من التفاصيل متوفرة أدناه ، ولكن ذلك قد يساعد على النظر في التعديلات التالية على الخاص setFoobar الطريقة:

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

مع هذا الرمز في المكان, قيمة foobar الملكية المعدلة بينما يتم تعيين ، ولكن السطر من التعليمات البرمجية سوف لا يزال يتم عرض القيمة باز!'.

التفاصيل:

كما أشار newacct, ، NSLog كود يعمل بسبب استخدام عامل التعيين ( = ) التي تحتوي على بعض سلوك معين في لغة C (وهو الهدف-C ويستند)

في 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);

الآن, في الهدف جيم, جهاز تسجيل الخط هو التعامل معها على النحو التالي:

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

(*) ملاحظة أن استخدام "temporaray متغير" أصف يهدف إلى توضيح مفهوم, و قد لا يعكس الواقع ما أي مترجم في الواقع لا تحت غطاء محرك السيارة.هذا النوع من تنفيذ التفاصيل حتى المبرمجين الذين يكتبون مترجم و كل واحد قد تفعل شيئا مختلفا.النتيجة النهائية, ومع ذلك, هو نفسه.

نصائح أخرى

وليس هناك حاجة لاستدعاء جالبة - أنه يحتوي على قيمة تم تعيينه هناك حق على نفس الخط. يمكنك التفكير في الأمر على النحو توسيع ل[mcInst setFoobar:@"BAZ!"], @"BAZ!".

وفي C، وتعيين تعبير، الذي يقيم إلى القيمة التي تم تعيينها

وهذا هو بسبب الطريقة التي يعمل بها المشغل C المهمة. كما هو موضح في معيار ANSI C:

و"هناك مخازن عامل التعيين قيمة في الكائن المعين من قبل المعامل الأيسر. تعبير الاحالة قيمة اليسار المعامل بعد الإحالة ... "

والتعبير مهمتك هي mcInst.foobar = @"BAZ!". ويبدو من المنطقي بالنسبة لي أنه على الرغم من الاحالة يعمل عن طريق استدعاء أسلوب على mcInst سلوك نفس مع C. قيمة التعبير مهمة هي المعامل الأيسر بعد الإحالة (@"BAZ!") بحيث يتم تمرير هذه القيمة إلى NSLog وظيفة.

وهذا هو نفس السلوك الذي يسمح لك لكتابة initialiser في أسلوب if (self = [super init]).

وP.S. إنها مسألة العدل أن نسأل لماذا سيدعو المترجم واضع على الممتلكات عند تعيين قيمة له وليس استدعاء جالبة عند استخدام قيمة mcInst.foobar بعد ذلك. انا اقول ان انها مجرد افتراض ان جالبة بإرجاع نفس القيمة التي تم تعيينها فقط إلى الخاصية، وبالتالي لا يسمى جالبة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top