OK, donc j'espère que c'est une question assez subjective pour les programmeurs, mais voilà. J'élargis continuellement ma connaissance des langages et des pratiques de génie logiciel ... et j'ai rencontré quelque chose qui n'a absolument aucun sens pour moi.
En C ++, les déclarations de classe incluent des private:
méthodes et des paramètres dans le fichier d'en-tête, qui, théoriquement, est ce que vous transmettez à l'utilisateur si vous en faites une lib.
Dans Objective-C, les @interface
s font à peu près la même chose, vous forçant à répertorier vos membres privés (au moins, il existe un moyen d'obtenir des méthodes privées dans le fichier d'implémentation).
D'après ce que je peux dire, Java et C # vous permettent de fournir une interface / un protocole qui peut déclarer toutes les propriétés / méthodes accessibles au public et donne au codeur la possibilité de masquer tous les détails de l'implémentation dans le fichier d'implémentation.
Pourquoi? L'encapsulation est l'un des principaux principes de la POO, pourquoi le C ++ et l'Obj-C n'ont-ils pas cette capacité de base? Existe-t-il une sorte de solution de contournement des meilleures pratiques pour Obj-C ou C ++ qui masque toute l' implémentation?
Merci,
la source
Réponses:
La question est de savoir si le compilateur doit savoir la taille d'un objet. Si c'est le cas, alors le compilateur doit connaître les membres privés afin de les compter.
En Java, il existe des types et des objets primitifs, et tous les objets sont alloués séparément, et les variables qui les contiennent sont vraiment des pointeurs. Par conséquent, puisqu'un pointeur est un objet de taille fixe, le compilateur sait quelle taille représente une variable, sans connaître la taille réelle de l'objet pointé. Le constructeur gère tout cela.
En C ++, il est possible d'avoir des objets représentés localement ou sur le tas. Par conséquent, le compilateur doit connaître la taille d'un objet pour pouvoir allouer une variable ou un tableau local.
Parfois, il est souhaitable de diviser la fonctionnalité de classe en une interface publique et un tout privé, et c'est là que la technique PIMPL (Pointer to IMPLementation) entre en jeu. La classe aura un pointeur vers une classe d'implémentation privée, et les méthodes de classe publique peuvent appeler cette.
la source
En raison de la conception de C ++, afin de créer un objet sur la pile, le compilateur doit savoir sa taille. Pour ce faire, il doit avoir tous les champs présents dans le fichier d'en-tête, car c'est tout ce que le compilateur peut voir lorsque l'en-tête est inclus.
Par exemple, si vous définissez une classe
sizeof(Foo)
est alorssizeof(a) + sizeof(b)
. S'il y avait un mécanisme pour séparer les champs privés, l'en-tête pourrait conteniravec
sizeof(Foo) = sizeof(a) + ???
.Si vous voulez vraiment cacher des données privées, essayez l'idiome pimpl, avec
dans l'en-tête et une définition pour
FooImpl
uniquement dansFoo
le fichier d'implémentation de.la source
Tout cela se résume au choix de conception.
Si vous souhaitez vraiment masquer les détails d'implémentation privée de la classe C ++ ou Objective-C, vous fournissez une ou plusieurs interfaces prises en charge par la classe (classe virtuelle pure C ++, Objective-C @protocol) et / ou vous créez la classe capable de se construire en fournissant une méthode d'usine statique ou un objet d'usine de classe.
La raison pour laquelle les variables privées sont exposées dans le fichier d'en-tête / déclaration de classe / interface @ est qu'un consommateur de votre classe peut avoir besoin d'en créer une nouvelle instance et que a
new MyClass()
ou[[MyClass alloc]init]
dans le code client a besoin du compilateur pour comprendre la taille d'une MyClass l'objet est de faire l'allocation.Java et C # ont également leurs variables privées détaillées dans la classe - ils ne font pas exception à cela, mais IMO le paradigme d'interface est beaucoup plus courant avec ces langages. Vous pouvez ne pas avoir le code source dans chaque cas, mais il y a suffisamment de métadonnées dans le code compilé / octet pour déduire ces informations. Comme C ++ et Objective-C n'ont pas ces métadonnées, la seule option est les détails réels de l'interface class / @. Dans le monde C ++ COM, vous n'exposez pas les variables privées d'aucune classe mais vous pouvez fournir le fichier d'en-tête - car la classe est pure virtuelle. Un objet de fabrique de classe est également enregistré pour créer les instances réelles, et il existe des métadonnées sous diverses formes.
En C ++ et Objective-C, il est moins difficile de distribuer le fichier d'en-tête que d'écrire et de maintenir un fichier de protocole interface / @ supplémentaire. C'est une des raisons pour lesquelles vous voyez si souvent l'implémentation privée exposée.
Une autre raison en C ++ est les modèles - le compilateur a besoin de connaître les détails de la classe afin de générer une version de cette classe spécialisée aux paramètres fournis. La taille des membres de la classe varie en fonction du paramétrage, il doit donc disposer de ces informations.
la source