Lorsqu'une structure de données (par exemple, une file d'attente) est implémentée à l'aide d'un langage POO, certains membres de la structure de données doivent être privés (par exemple, le nombre d'éléments de la file d'attente).
Une file d'attente peut également être implémentée dans un langage procédural à l'aide d'un struct
et d'un ensemble de fonctions qui fonctionnent sur le serveur struct
. Cependant, dans un langage procédural, vous ne pouvez pas faire des membres d'un struct
privé. Les membres d'une structure de données implémentée dans un langage procédural ont-ils été rendus publics ou y avait-il un truc pour les rendre privés?
object-oriented
data-structures
history
Christopher
la source
la source
Réponses:
OOP n'a pas inventé l'encapsulation et n'est pas synonyme d'encapsulation. De nombreux langages POO n'ont pas de modificateurs d'accès de style C ++ / Java. De nombreuses langues non-POO disposent de diverses techniques pour offrir une encapsulation.
Une approche classique de l’encapsulation est la fermeture , utilisée dans la programmation fonctionnelle . C'est beaucoup plus vieux que la POO mais est en quelque sorte équivalent. Par exemple, en JavaScript, nous pourrions créer un objet comme ceci:
L'
plus2
objet ci-dessus n'a aucun membre qui permettrait un accès direct àx
- il est entièrement encapsulé. Laadd()
méthode est une fermeture sur lax
variable.Le langage C prend en charge certains types d'encapsulation via son mécanisme de fichier d'en-tête , notamment la technique du pointeur opaque . En C, il est possible de déclarer un nom de structure sans définir ses membres. À ce stade, aucune variable du type de cette structure ne peut être utilisée, mais nous pouvons utiliser librement les pointeurs sur cette structure (car la taille d'un pointeur de structure est connue au moment de la compilation). Par exemple, considérons ce fichier d’en-tête:
Nous pouvons maintenant écrire du code qui utilise cette interface Adder, sans avoir accès à ses champs, par exemple:
Et voici les détails de la mise en œuvre totalement encapsulée:
Il existe également la classe des langages de programmation modulaires , qui se concentre sur les interfaces au niveau des modules. La famille de langues ML incl. OCaml inclut une approche intéressante des modules appelés foncteurs . La programmation modulaire occultée et en grande partie occultée par la programmation orientée objet, mais de nombreux avantages supposés de la programmation orientée objet concernent davantage la modularité que l'orientation objet.
Il y a aussi l'observation que les classes dans les langages POO tels que C ++ ou Java ne sont souvent pas utilisées pour les objets (dans le sens d'entités qui résolvent des opérations par liaison / dispatch dynamique tardive) mais simplement pour les types de données abstraits (où nous définissons une interface publique qui cache détails de la mise en œuvre interne). Le document intitulé Comprendre l'abstraction des données, revisité (Cook, 2009) examine cette différence plus en détail.
Mais oui, beaucoup de langues n’ont aucun mécanisme d’encapsulation. Dans ces langues, les membres de la structure sont laissés publics. Tout au plus, il y aurait une convention de nommage décourageant l'utilisation. Par exemple, je pense que Pascal n'avait pas de mécanisme d'encapsulation utile.
la source
Adder self = malloc(sizeof(Adder));
? Il y a une raison pour laquelle les pointeurs sont courants etsizeof(TYPE)
sont généralement mal vus.sizeof(*Adder)
, car ce*Adder
n'est pas un type, tout comme ce*int *
n'est pas un type. L'expressionT t = malloc(sizeof *t)
est à la fois idiomatique et correcte. Voir mon édition.private static
variables en Java. De même en C, vous pouvez utiliser des pointeurs opaques pour transmettre des données en Pascal sans déclarer ce dont il s'agissait. MacOS classique utilisait beaucoup de pointeurs opaques, car des parties publiques et privées d’un enregistrement (structure de données) pouvaient être transmises ensemble. Je me souviens que Windows Manager en faisait beaucoup puisque certaines parties du Window Record étaient publiques mais que certaines informations internes étaient également incluses._private_member
etoutput_property_
, ou à des techniques plus avancées de création d'objets imputables.Premièrement, être procédural ou orienté objet n'a rien à voir avec public ou privé. Beaucoup de langages orientés objet n'ont aucune notion de contrôle d'accès.
Deuxièmement, dans "C" - que la plupart des gens appellent procédure, et non orientée objet, vous pouvez utiliser de nombreuses astuces pour rendre les choses privées. Un très commun consiste à utiliser des pointeurs opaques (par exemple, void *). Ou - vous pouvez transférer la déclaration d'un objet sans la définir dans un fichier d'en-tête.
foo.h:
foo.c:
Regardez le SDK de Windows! Il utilise HANDLE et UINT_PTR, entre autres choses, pour constituer des descripteurs génériques de la mémoire utilisée dans les API, ce qui permet de rendre les implémentations privées.
la source
"Les types de données opaques" était un concept bien connu lorsque j'ai obtenu mon diplôme en informatique il y a 30 ans. Nous n'avons pas couvert la POO car ce n'était pas d'usage courant à l'époque et la "programmation fonctionnelle" était considérée comme plus correcte.
Modula-2 avait un support direct pour eux, voir https://www.modula2.org/reference/modules.php .
Lewis Pringle a déjà expliqué comment la déclaration anticipée d'une structure peut être utilisée en C. Contrairement à Module-2, une fonction de fabrique devait être fournie pour créer l'objet. ( Les méthodes virtuelles étaient également faciles à implémenter en C, le premier membre d'une structure étant un pointeur sur une autre structure contenant des pointeurs de fonction sur les méthodes.)
Souvent, la convention était également utilisée. Par exemple, aucun champ commençant par «_» ne doit être accessible en dehors du fichier contenant les données. Cela a été facilement appliqué par la création d’outils de vérification personnalisés.
Tous les projets à grande échelle sur lesquels j'ai travaillé (avant de passer à C ++ puis à C #) disposaient d'un système en place pour empêcher l'accès aux données "privées" par un code erroné. C'était juste un peu moins standardisé que maintenant.
la source
Notez qu'il existe de nombreuses langues OO sans possibilité intégrée de marquer les membres comme privés. Cela peut être fait par convention, sans qu'il soit nécessaire que le compilateur applique la confidentialité. Par exemple, les personnes préfixent souvent les variables privées par un trait de soulignement.
Il existe des techniques pour rendre plus difficile l'accès aux variables "privées", la plus courante étant l' idiome PIMPL . Cela place vos variables privées dans une structure séparée, avec juste un pointeur alloué dans vos fichiers d’en-têtes publics. Cela signifie une déréférence supplémentaire et une conversion pour obtenir toutes les variables privées, quelque chose comme
((private_impl)(obj->private))->actual_value
, ce qui devient gênant, donc, en pratique, il est rarement utilisé.la source
Les structures de données n'avaient pas de "membres", seulement des champs de données (en supposant qu'il s'agisse d'un type d'enregistrement). La visibilité était généralement définie pour tout le type. Cependant, cela n’est peut-être pas aussi contraignant que vous le pensez, car les fonctions ne faisaient pas partie du dossier.
Revenons un peu en arrière et obtenons un peu d'histoire ici ...
Le paradigme de programmation dominant avant la POO s'appelait la programmation structurée . L’objectif principal initial était d’éviter l’utilisation d’énoncés de saut non structurés ("goto"). Il s’agit d’un paradigme axé sur les flux de contrôle (alors que la programmation orientée objet est davantage axée sur les données), mais il s’agissait toujours d’une extension naturelle de ce dernier pour tenter de garder les données structurées logiquement, tout comme le code.
Une autre conséquence de la programmation structurée a été la dissimulation d'informations , l'idée selon laquelle les implémentations de la structure du code (qui est susceptible de changer assez souvent) devraient être séparées de l'interface (idéalement, elles ne devraient pas changer autant). C'est maintenant un dogme, mais à l'époque jadis, beaucoup de gens considéraient qu'il était préférable que chaque développeur connaisse les détails du système dans son ensemble. Il s'agissait donc à un moment d'une idée controversée. L'édition originale de The Mythical Man Month, de Brook, plaidait en réalité contre la dissimulation d'informations.
Les langages de programmation ultérieurs conçus explicitement pour être bons Les langages de programmation structurés (par exemple, Modula-2 et Ada) incluaient généralement le masquage d’informations en tant que concept fondamental, construit autour d’une sorte de concept de fonctionnalité cohérente de fonctions (et de tous types, constantes et objets dont ils pourraient avoir besoin). Dans Modula-2, ils ont été appelés "Modules", dans Ada "Packages". Beaucoup de langages POO modernes appellent le même concept "espaces de noms". Ces espaces de noms constituaient le fondement organisationnel du développement de ces langages et pouvaient, dans la plupart des cas, être utilisés de la même manière que les classes POO (sans prise en charge réelle de l'héritage, bien entendu).
Ainsi, dans Modula-2 et Ada (83), vous pouvez déclarer une routine, un type, une constante ou un objet dans un espace de noms privé ou public, mais si vous aviez un type d'enregistrement, il n'existait aucun moyen (facile) de déclarer certains champs d' enregistrement public. et d'autres privés. Tout votre dossier est public ou non.
la source
object.method()
invocation est simplement du sucre syntaxique. Important IMHO - voir le principe d’uniformité d’accès / de référence de Meyer - mais toujours du sucre syntaxique.object.method()
une forme alternativemethod(object, ...)
aux personnes qui ne pouvaient tout simplement pas faire le saut conceptuel.En C, vous pouvez déjà faire passer des pointeurs vers des types déclarés mais non définis, comme d'autres l'ont dit, limitant ainsi l'accès à tous les champs.
Vous pouvez également avoir des fonctions privées et publiques module par module. Les fonctions déclarées statiques dans le fichier source ne sont pas visibles de l'extérieur, même si vous essayez de deviner leur nom. De même, vous pouvez avoir des variables globales statiques au niveau du fichier, ce qui est généralement une mauvaise pratique, mais permet une isolation par module.
Il est probablement important de souligner que la restriction d'accès en tant que convention bien normalisée plutôt que comme construction imposée par la langue fonctionne parfaitement (voir Python). De plus, la restriction de l'accès aux champs d'objet ne protégera le programmeur que lorsqu'il sera nécessaire de modifier la valeur des données dans un objet après sa création. Ce qui est déjà une odeur de code. On peut soutenir que le
const
mot clé de C et en particulier C ++ pour les méthodes et les arguments de fonction est une aide beaucoup plus utile pour le programmeur que pour celui de Java, qui est plutôt médiocrefinal
.la source
static
les données et opérations globales (ce qui signifiait qu'elles n'étaient pas présentées à l'éditeur de liens pour être utilisées à partir d'autres compilations). Vous pouvez raisonnablement affirmer que tout soutien de C avait de bonnes pratiques en matière de conception de logiciels, mis à part qu'il s'agissait en quelque sorte d'un bidouillage, et qu'il ne faisait pas partie de la conception originale du langage en 1972.Si votre définition de Public est la possibilité d'accéder à la mise en œuvre et aux données / propriétés via votre propre code à tout moment, la réponse est simplement: Oui . Cependant, il a été résumé par divers moyens - en fonction de la langue.
J'espère que ceci a répondu succinctement à votre question.
la source
Voici un contre-exemple très simple: en Java,
interface
s définit des objets, maisclass
ce n'est pas le cas. Aclass
définit un type de données abstrait, pas un objet.Ainsi, chaque fois que vous utilisez
private
une versionclass
Java, vous avez un exemple de structure de données avec des membres privés qui n'est pas orientée objet.la source