Le load
message
Le moteur d'exécution envoie le load
message à 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 load
message 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 load
mé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 load
message à l' Superclass
objet de classe. Il n'envoie pas le load
message à l' Subclass
objet de classe, même s'il Subclass
hérite de la méthode de Superclass
.
Le moteur d'exécution envoie le load
message à un objet de classe après qu'il a envoyé le load
message à 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 load
message si elle implémente la load
méthode, que votre processus utilise ou non la classe à une autre fin.
Vous pouvez voir comment le runtime recherche la load
méthode en tant que cas spécial dans le _class_getLoadMethod
of objc-runtime-new.mm
, et l'appelle directement depuis call_class_loads
in objc-loadmethod.mm
.
Le runtime exécute également la load
mé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 initialize
méthode
Le runtime appelle la initialize
méthode sur un objet de classe juste avant d'envoyer le premier message (autre que load
ou 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 initialize
mé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 initialize
est la suivante:
@implementation Someclass
+ (void)initialize {
if (self == [Someclass class]) {
// do whatever
}
}
Le but de ce modèle est d'éviter de Someclass
se réinitialiser quand il a une sous-classe qui ne s'implémente pas initialize
.
Le runtime envoie le initialize
message dans la _class_initialize
fonction dans objc-initialize.mm
. Vous pouvez voir qu'il utilise objc_msgSend
pour 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.
+load
est envoyé séparément pour les catégories; c'est-à-dire que chaque catégorie d'une classe peut contenir sa propre+load
méthode.