Извикване на [[super allocWithZone:nil] init], механизъм за съобщения

f. д. (само за по-ясно разбиране на механизма на съобщенията) Имам клас

MyClass.h

@interface MyClass : NSObject {
   int ivar1;
   int ivar2;
}

+ (id)instance;

@end

MyClass.m

static MyClass* volatile _sInstance = nil;

@implementation MyClass

+ (id)instance {
       if (!_sInstance) {
       @synchronized(self) {
           if (!_sInstance) {
               _sInstance = [[super allocWithZone:nil] init];
           }
       }
   }
   return _sInstance;
}

@end

Какво всъщност ще бъде изпратено в objc_msgSend при извикване на [super allocWithZone:nil]?

objc_msgSend([MyClass class], "allocWithZone", nil) or objc_msgSend([NSObject class], "allocWithZone", nil) ?

На практика мисля, че това се нарича objc_msgSend(self, "allocWithZone", nil) и в този случай self == [MyClass class];

Искам да съм сигурен, че паметта за ivar1 и ivar2 ще бъде разпределена.

Вярно ли е, че когато извикаме super в метода на класа, във функцията objc_msgSend() се предава аргументът "self", който в нашия случай е клас обект на дете? И allocWithZone ще "погледне" обекта на дъщерния клас, за да види колко памет трябва да бъде разпределена за ivar1 и ivar2.

Благодаря!


person BergP    schedule 15.08.2013    source източник
comment
Може би пропускам нещо, защото защо бихте разпределили екземпляр на MyClass, като извикате [[MyClass super] alloc]?   -  person trojanfoe    schedule 15.08.2013
comment
@trojanfoe Може да е метод за разпределение, не е толкова важно )   -  person BergP    schedule 15.08.2013
comment
Но това, което не разбирам, е как извикването на [super alloc] (или [super allocWithZone]) ще разпредели достатъчно място за допълнителните променливи на екземпляр в self?   -  person trojanfoe    schedule 15.08.2013
comment
Така че това беше въпросът ми) Мисля, че ще бъде предадено само, което ще бъде [клас MyClass], а от [клас MyClass] ще се види колко място ще бъде достатъчно   -  person BergP    schedule 15.08.2013
comment
@trojanfoe Няма значение дали да извикате alloc, използвайки super или self. Средата за изпълнение използва приемника, за да определи размера на екземпляра.   -  person Nikolai Ruhe    schedule 15.08.2013
comment
Както обяснява моят отговор, суперобаждането изпраща както суперкласа, така и приемника към средата за изпълнение. Тогава само приемникът се предава на реализацията на метода.   -  person Nikolai Ruhe    schedule 15.08.2013
comment
@NikolaiRuhe Добре благодаря - интересно.   -  person trojanfoe    schedule 15.08.2013


Отговори (1)


Всяко съобщение до super се превежда от компилатора в objc_msgSendSuper (не objc_msgSend). Първият аргумент е указател към структура. Структурата съдържа указател към суперкласа на текущата реализация и указател към приемника. Първият е необходим по време на изпълнение, за да се търси отменената реализация, вторият се използва като първи аргумент.

В случай на метод на клас приемникът отново е указател на клас, но не е същият като super_class. Във вашия случай приемникът е MyClass указател, докато super_class указател би бил NSObject.

Две странични бележки: препоръчвам да не влагате енергия в писането на най-фантастичния Singleton. По-добре оставете на разработчика да създаде свои собствени екземпляри или да използва предоставения споделен екземпляр. И моля, обърнете внимание, че заключването с двойна проверка е повредено.

person Nikolai Ruhe    schedule 15.08.2013