La réponse est ... eh bien ... simple. Simplicité et cohérence, en fait.
Objective-C est purement dynamique au moment de l'envoi de la méthode. En particulier, chaque envoi de méthode passe par le même point de résolution de méthode dynamique que chaque autre envoi de méthode. Au moment de l'exécution, chaque implémentation de méthode a exactement la même exposition et toutes les API fournies par le runtime Objective-C qui fonctionnent avec des méthodes et des sélecteurs fonctionnent de la même manière dans toutes les méthodes.
Comme beaucoup l'ont répondu (ici et dans d'autres questions), les méthodes privées à la compilation sont supportées; si une classe ne déclare pas une méthode dans son interface accessible au public, alors cette méthode pourrait tout aussi bien ne pas exister en ce qui concerne votre code. En d'autres termes, vous pouvez obtenir toutes les différentes combinaisons de visibilité souhaitées au moment de la compilation en organisant votre projet de manière appropriée.
Il y a peu d'avantages à dupliquer la même fonctionnalité dans le runtime. Cela ajouterait énormément de complexité et de frais généraux. Et même avec toute cette complexité, cela n'empêcherait toujours pas tous les développeurs, sauf les plus occasionnels, d'exécuter vos méthodes supposées "privées".
EDIT: L'une des hypothèses que j'ai remarquées est que les messages privés devraient passer par l'exécution, ce qui entraînerait une surcharge potentiellement importante. Est-ce absolument vrai?
Oui, ça l'est. Il n'y a aucune raison de supposer que l'implémenteur d'une classe ne souhaite pas utiliser toutes les fonctionnalités d'Objective-C dans l'implémentation, et cela signifie que la répartition dynamique doit avoir lieu. Cependant , il n'y a aucune raison particulière pour laquelle les méthodes privées ne peuvent pas être distribuées par une variante spéciale de objc_msgSend()
, puisque le compilateur saurait qu'elles sont privées; c'est-à-dire que cela pourrait être réalisé en ajoutant une table de méthode uniquement privée à la Class
structure.
Il n'y aurait aucun moyen pour une méthode privée de court-circuiter cette vérification ou de sauter le runtime?
Il ne pouvait pas ignorer le runtime, mais le runtime n'aurait pas nécessairement à vérifier les méthodes privées.
Cela dit, il n'y a aucune raison qu'un tiers ne puisse pas appeler délibérément objc_msgSendPrivate()
un objet, en dehors de la mise en œuvre de cet objet, et certaines choses (KVO, par exemple) devraient le faire. En effet, ce serait juste une convention et guère mieux en pratique que de préfixer les sélecteurs de méthodes privées ou de ne pas les mentionner dans l'en-tête de l'interface.
Faire ainsi, cependant, minerait la nature dynamique pure de la langue. Chaque envoi de méthode ne passerait plus par un mécanisme d'envoi identique. Au lieu de cela, vous vous retrouveriez dans une situation où la plupart des méthodes se comportent d'une manière et une petite poignée est simplement différente.
Cela va au-delà du runtime car il existe de nombreux mécanismes dans Cocoa basés sur le dynamisme cohérent d'Objective-C. Par exemple, le codage des valeurs clés et l'observation des valeurs clés devraient soit être très fortement modifiés pour prendre en charge les méthodes privées - très probablement en créant une faille exploitable - ou les méthodes privées seraient incompatibles.