Le loadmessage
Le moteur d'exécution envoie le loadmessage à chaque objet de classe, très peu de temps après le chargement de l'objet de classe dans l'espace d'adressage du processus. Pour les classes qui font partie du fichier exécutable du programme, le runtime envoie le loadmessage très tôt dans la durée de vie du processus. Pour les classes qui se trouvent dans une bibliothèque partagée (chargée dynamiquement), le moteur d'exécution envoie le message de chargement juste après que la bibliothèque partagée est chargée dans l'espace d'adressage du processus.
De plus, le runtime n'envoie loadà un objet de classe que si cet objet de classe lui-même implémente la loadméthode. Exemple:
@interface Superclass : NSObject
@end
@interface Subclass : Superclass
@end
@implementation Superclass
+ (void)load {
NSLog(@"in Superclass load");
}
@end
@implementation Subclass
// ... load not implemented in this class
@end
Le runtime envoie le loadmessage à l' Superclassobjet de classe. Il n'envoie pas le loadmessage à l' Subclassobjet de classe, même s'il Subclasshérite de la méthode de Superclass.
Le moteur d'exécution envoie le loadmessage à un objet de classe après qu'il a envoyé le loadmessage à tous les objets de superclasse de la classe (si ces objets de superclasse sont implémentés load) et à tous les objets de classe dans les bibliothèques partagées vers lesquelles vous créez un lien. Mais vous ne savez pas encore quelles autres classes de votre propre exécutable ont été reçues load.
Chaque classe que votre processus charge dans son espace d'adressage recevra un loadmessage si elle implémente la loadméthode, que votre processus utilise ou non la classe à une autre fin.
Vous pouvez voir comment le runtime recherche la loadméthode en tant que cas spécial dans le _class_getLoadMethodof objc-runtime-new.mm, et l'appelle directement depuis call_class_loadsin objc-loadmethod.mm.
Le runtime exécute également la loadméthode de chaque catégorie qu'il charge, même si plusieurs catégories sur la même classe implémentent load. C'est inhabituel. Normalement, si deux catégories définissent la même méthode sur la même classe, l'une des méthodes "gagnera" et sera utilisée, et l'autre méthode ne sera jamais appelée.
La initializeméthode
Le runtime appelle la initializeméthode sur un objet de classe juste avant d'envoyer le premier message (autre que loadou initialize) à l'objet de classe ou à toute instance de la classe. Ce message est envoyé en utilisant le mécanisme normal, donc si votre classe n'implémente pas initialize, mais hérite d'une classe qui le fait, alors votre classe utilisera sa superclasse initialize. Le runtime enverra d'abord le initializeà toutes les superclasses d'une classe (si les superclasses n'ont pas déjà été envoyées initialize).
Exemple:
@interface Superclass : NSObject
@end
@interface Subclass : Superclass
@end
@implementation Superclass
+ (void)initialize {
NSLog(@"in Superclass initialize; self = %@", self);
}
@end
@implementation Subclass
// ... initialize not implemented in this class
@end
int main(int argc, char *argv[]) {
@autoreleasepool {
Subclass *object = [[Subclass alloc] init];
}
return 0;
}
Ce programme imprime deux lignes de sortie:
2012-11-10 16:18:38.984 testApp[7498:c07] in Superclass initialize; self = Superclass
2012-11-10 16:18:38.987 testApp[7498:c07] in Superclass initialize; self = Subclass
Puisque le système envoie la initializeméthode paresseusement, une classe ne recevra le message que si votre programme envoie réellement des messages à la classe (ou à une sous-classe, ou à des instances de la classe ou des sous-classes). Et au moment où vous recevez initialize, chaque classe de votre processus devrait déjà avoir reçu load(le cas échéant).
La manière canonique de mettre en œuvre initializeest la suivante:
@implementation Someclass
+ (void)initialize {
if (self == [Someclass class]) {
// do whatever
}
}
Le but de ce modèle est d'éviter de Someclassse réinitialiser quand il a une sous-classe qui ne s'implémente pas initialize.
Le runtime envoie le initializemessage dans la _class_initializefonction dans objc-initialize.mm. Vous pouvez voir qu'il utilise objc_msgSendpour l'envoyer, qui est la fonction normale d'envoi de messages.
Lectures complémentaires
Consultez les questions-réponses de Mike Ash sur ce sujet.
+loadest envoyé séparément pour les catégories; c'est-à-dire que chaque catégorie d'une classe peut contenir sa propre+loadméthode.