Je viens d'un milieu C ++ et je fais tout C # dans mon travail actuel et je viens de lire beaucoup de questions et réponses sur la différence entre les champs publics et les propriétés et tous les va-et-vient dans les variations et les incarnations de ce question de base (par exemple, ce message SO et toutes les questions connexes liées ). Toutes ces questions sont abordées en termes de différences pratiques qui tiennent pour acquis l'existence d'un système de propriété, mais je pense qu'il serait bon d'aborder ce sujet en termes de ce que les concepteurs de toutes les langues qui ont décidé de soutenir les propriétés dans le premier l'endroit pensait (consultez la liste dans l'article Wikipedia ici). Comment la POO a évolué du C ++ / Java pour s'étendre dans ce que l'article de Wikipedia identifie de manière intéressante comme un milieu entre les méthodes et les données des membres:
"Autrement dit, les propriétés sont intermédiaires entre le code membre (méthodes) et les données membres (variables d'instance) de la classe, et les propriétés fournissent un niveau d'encapsulation plus élevé que les champs publics."
MSDN ajoute des informations supplémentaires:
"Bien que les propriétés soient techniquement très similaires aux méthodes, elles sont très différentes en termes de scénarios d'utilisation. Elles doivent être considérées comme des champs intelligents. Elles ont la syntaxe d'appel des champs et la flexibilité des méthodes."
J'aimerais savoir comment on en est arrivé à ce que ce niveau intermédiaire d'encapsulation s'est avéré utile pour la programmation en général. Je suppose que ce concept n'était pas présent lors de la première incarnation des langages de programmation qui exprimaient le paradigme OOP.
BMI = bob.weight/sq(bob.height)
lit mieux sans()
IMO.Réponses:
Il s'agit de l'encapsulation et du principe d'accès uniforme.
Un objet doit être en mesure de répondre à un message en renvoyant des données existantes ou en exécutant une méthode, mais l'expéditeur ne doit pas être en mesure de dire laquelle est laquelle. Ou si vous voyez cela du côté de l'expéditeur: l'expéditeur doit pouvoir accéder aux données existantes ou exécuter une méthode via une interface uniforme.
Il existe plusieurs façons d'y parvenir:
se débarrasser complètement des données, il suffit d'avoir des méthodes (Newspeak le fait)
se débarrasser complètement des méthodes, juste avoir des données (Self fait cela, les "méthodes" ne sont que des
Method
objets affectés aux variables d'instance, les variables d'instance sont recherchées avec une répartition virtuelle)ne pas faire de distinction syntaxique ou sémantique entre les méthodes et les données (Scala le fait, l'accès à un champ est impossible à distinguer syntaxiquement d'appeler une méthode sans liste d'arguments (
foo.bar
), l'affectation à un champ est impossible à distinguer syntaxiquement d'appeler une méthode spécialement nommée (foo.bar = baz
) est la même commefoo.bar_=(baz)
c'est- à- dire appeler une méthode nomméefoo_=
, et les valeurs en lecture seule peuvent être écrasées ou implémentées par une méthode sans liste de paramètres (ieval foo
) dans une superclasse peuvent être écrasées (ouabstract
val
être implémentées) dans une sous-classe avec une méthodedef foo
)Java, cependant, ne suit pas le principe d'accès uniforme. En Java, il est possible de distinguer entre l'accès aux données et l'exécution d'une méthode.
foo.bar
est différent defoo.bar()
. La raison en est que les champs et les méthodes sont sémantiquement et syntaxiquement distincts.C # essaie de résoudre ce problème en ajoutant des propriétés au langage, essentiellement des méthodes qui ressemblent à des champs. Cependant, les appels de méthode sont toujours différents des accès aux champs et aux propriétés. Les champs et les propriétés ont désormais un accès uniforme, mais pas les méthodes.
Donc, cela ne résout pas réellement le problème: vous ne pouvez pas résoudre deux façons différentes d'accéder aux choses en ajoutant une troisième façon d'accéder aux choses! Même si cette troisième voie ressemble à l'une des deux autres façons, vous aurez toujours (au moins) deux façons différentes. Vous ne pouvez le corriger qu'en vous débarrassant de toutes les différentes manières sauf une ou en supprimant les différences.
C'est parfaitement bien d'avoir un langage avec des méthodes, des propriétés et des champs, mais les trois devraient avoir un accès uniforme.
la source
Eh bien, je ne suis pas sûr à 100%, mais je suppose que les choses sont probablement plus simples que vous ne le pensez. Depuis les écoles de modélisation OO des années 90, il y avait une demande pour des classes de modélisation avec des attributs de membre encapsulés, et lorsqu'elles sont implémentées dans des langages comme C ++ ou Java, cela conduit généralement à du code avec beaucoup de getters et setters, donc beaucoup de «bruit» code pour une exigence relativement simple. Notez que la plupart (probablement tous, n'ont pas vérifié cela) les langues répertoriées dans votre article Wikipedia lié ont commencé à introduire des «propriétés» des objets à la fin des années 90 ou plus tard.
Je suppose que c'est la principale raison pour laquelle les concepteurs de langage ont décidé d'ajouter du sucre syntaxique pour réduire ce bruit. Et bien que les propriétés ne soient sûrement pas un «concept OO de base», elles ont au moins quelque chose à voir avec l'orientation des objets. Ils ne montrent pas "une évolution de la POO" (comme le suppose le titre de votre question), mais ils prennent en charge la modélisation OO au niveau du langage de programmation pour faciliter la mise en œuvre.
la source
Vous l'avez à l'envers (en quelque sorte). Lambda Calculus existe à peu près comme la base formelle de base pour les langages de programmation, et ce depuis des décennies. Il n'a pas de champs.
Pour modéliser l'état mutable, vous devez effectuer deux abstractions. L'un représente la définition d'un état, et un autre qui récupère cet état (chapitre 13 dans ma version de TaPL pour référence). Semble familier? D'un fond théorique , OO n'a pas évolué pour avoir ce genre de choses. OO a lu les langages de programmation 101 et a fait un petit pas en avant.
D'un point de vue pratique , il existe deux motivations assez claires. Vous venez d'un arrière-plan C ++, alors que devrait-il se passer si vous aviez un champ public - disons ... le texte dans une zone de texte. Que se passe-t-il lorsque vous souhaitez modifier votre conception afin que "chaque fois que cette zone de texte change, faites bof"? Vous pouvez tuer ce champ, créer une fonction ou deux et câbler cette logique, car vous ne pouvez pas faire confiance aux développeurs pour appeler eux-mêmes "UpdateTextbox". Il s'agit d'un changement très important dans votre API (et malheureusement encore un changement majeur dans l'implémentation des propriétés de .NET). Ce type de comportement est partout dans l'API Windows. Étant donné que c'est un gros problème chez Microsoft, C # voulait probablement rendre cela moins douloureux.
L'autre grande motivation est Java Beans et leurs proches. Un certain nombre de cadres ont été construits pour utiliser la réflexion Java pour rechercher
GetX
etSetX
associer et les traiter efficacement comme des propriétés modernes. Mais comme il ne s'agissait pas de véritables constructions de langage, ces cadres étaient fragiles et peu familiers. Si vous tapiez un nom, les choses se briseraient silencieusement. Si l'un a été refactorisé, rien ne bouge de l'autre côté de la propriété. Et faire tout le passe-partout field / get / set était bavard et fastidieux (même pour Java!). Depuis que C # a été développé en grande partie comme "Java avec leçons apprises", ce genre de douleur était l'une de ces leçons.Mais le plus gros, c'est que le concept immobilier a réussi. C'est facile à comprendre, c'est facile à utiliser. Celles-ci facilitent grandement l'adoption et, en tant qu'outil , les programmeurs ont constaté que les propriétés résolvent un sous-ensemble de problèmes plus proprement que les fonctions ou les champs.
la source
Dans .net en particulier, les propriétés proviennent des anciens jours Visual Basic qui, en l'occurrence, n'étaient pas orientés objet dans la façon dont nous y pensons aujourd'hui. Il a été largement construit autour du système COM alors nouveau qui superficiellement traitait tout non pas nécessairement comme des classes mais en termes de composants qui exposeraient des propriétés accessibles à la fois dans le code mais aussi dans les éditeurs graphiques. Lorsque VB et le C # nouvellement créé ont été fusionnés dans .net, VB a gagné beaucoup de fonctionnalités OOP et ils ont conservé les propriétés car les supprimer serait comme un pas en arrière - imaginez si l'outil de mise à jour automatique du code qu'ils avaient dans Visual Studio avait été remplacer toutes vos propriétés par des getters et des setters et rompait la compatibilité avec toutes les bibliothèques COM. Il serait logique de les soutenir en tout.
la source
Les propriétés n'ont rien à voir avec la programmation orientée objet, car les propriétés ne sont que du sucre syntaxique. Les propriétés ressemblent à des champs superficiellement, et dans le monde .net, il est recommandé qu'elles se comportent comme des champs à certains égards, mais ce ne sont en aucun cas des champs. Les propriétés sont du sucre syntaxique pour une ou deux méthodes: une pour obtenir une valeur et une pour définir une valeur. La méthode set ou la méthode get peut être omise, mais pas les deux. Il se peut qu'aucun champ ne stocke la valeur renvoyée par la méthode get. Parce qu'ils partagent une syntaxe avec les champs et qu'ils utilisent souvent des champs, les gens associent des propriétés aux champs.
Les propriétés ont des avantages sur les champs:
Étant donné que les propriétés sont l'abstraction des champs et pour des raisons de syntaxe, des langages tels que C # ont adopté la syntaxe des champs pour les propriétés.
la source
C'est une question d' implémentation versus d' implication . Les propriétés étaient en POO avant que C ++ ou Java n'entrent en scène (elles étaient là, avec une certaine rugosité autour des bords, dans Simula, et elles sont fondamentales pour Smalltalk). Les entités avec des propriétés sont conceptuellement différentes des valeurs avec du code attaché. Les préfixes get & set dans certaines conventions linguistiques ne servent qu'à brouiller les eaux; ils vous font prendre conscience de la différence entre les champs et les propriétés, en supposant que les champs peuvent être accédés directement sans get / set d'une manière idiomatique à la langue, et c'est une fuite.
Le but de la POO est de traiter les choses comme si elles étaient des entités dans le monde "réel", pas seulement comme des structures avec du code mélangé. Un autre programmeur devrait avoir besoin de savoir très, très peu de choses sur la façon dont j'ai implémenté les choses, et ne devrait pas du tout se préoccuper de laquelle des différentes valeurs qu’elles sont autorisées à obtenir et / ou définir sont réelles et lesquelles sont virtuelles. Si vous rencontrez un de mes vecteurs, vous ne devriez pas avoir besoin de savoir si je stocke l'angle et la magnitude ou des composants réels et imaginaires internes à l'objet vectoriel. Si je change la représentation dans la version 2.0 de ma bibliothèque, cela ne devrait pas du tout affecter votre code (bien que vous souhaitiez peut-être profiter des nouvelles fonctionnalités intéressantes). De même, certaines entités peuvent avoir des propriétés qui dépendent de données externes à l'entité, mais qui sont sans aucun doute des propriétés d'un point de vue lexical. Vous demandez aux gens "quel âge avez-vous", pas "veuillez effectuer le calcul qui me révélera votre âge", même si vous savez que les données disponibles pour cet "objet" sont la date de naissance (un membre privé immuable) et celle d'aujourd'hui date (propriété environnementale publique à incrémentation automatique, dépendante du fuseau horaire, de l'heure d'été et de la ligne de date internationale). L'âge est une propriété, pas une méthode, même s'il faut un certain calcul pour y arriver et ne peut pas (sauf dans les représentations par ordinateur jouet d'objets avec des durées de vie artificiellement limitées) être stocké comme un champ. même si vous savez que les données disponibles pour cet "objet" sont la date de naissance (un membre privé immuable) et la date d'aujourd'hui (une propriété environnementale publique à incrémentation automatique, en fonction du fuseau horaire, de l'heure d'été et de la ligne de date internationale ). L'âge est une propriété, pas une méthode, même s'il faut un certain calcul pour y arriver et ne peut pas (sauf dans les représentations par ordinateur jouet d'objets avec des durées de vie artificiellement limitées) être stocké comme un champ. même si vous savez que les données disponibles pour cet "objet" sont la date de naissance (un membre privé immuable) et la date d'aujourd'hui (une propriété environnementale publique à incrémentation automatique, en fonction du fuseau horaire, de l'heure d'été et de la ligne de date internationale ). L'âge est une propriété, pas une méthode, même s'il faut un certain calcul pour y arriver et ne peut pas (sauf dans les représentations par ordinateur jouet d'objets avec des durées de vie artificiellement limitées) être stocké comme un champ.
Plutôt que de considérer les propriétés comme l'enfant bâtard des champs et des méthodes, c'est beaucoup plus satisfaisant que les méthodes comme une sorte de propriété spécialisée - des choses que vos entités peuvent faire plutôt que des choses qu'elles sont. Sinon, vous ne traitez pas conceptuellement avec des objets / entités, vous traitez avec des collections de données auxquelles du code est attaché. Les implémentations peuvent être identiques, mais les implications sont différentes.
Il va sans dire, cependant, que cette abstraction a un coût. Si un programmeur utilisant une classe ne peut pas dire s'il accède aux données telles qu'elles sont stockées ou obtient / définit des valeurs qui doivent être calculées, alors il y aura un niveau auquel le langage est également nécessairement incertain (et peut donc exiger que tout nécessite un code intermédiaire entre les accesseurs / sélecteurs et les valeurs). Il n'y a rien de mal conceptuellement avec les "structures avec du code" - elles peuvent certainement être beaucoup plus efficaces - mais elles fuient l'implémentation partout, et c'est l'une des choses que la POO est censée éliminer.
la source
Absolument rien du tout. Les propriétés et la POO n'ont rien à voir les unes avec les autres. Les propriétés ne sont rien de plus que du sucre syntaxique pour les appels de fonction, et ont donc exactement le même attachement OOP que les appels de fonction font, c'est-à-dire aucun.
Soit dit en passant, Wikipedia est complètement incorrect. Le modèle getMember / setMember que vous voyez en Java offre exactement les mêmes avantages (et inconvénients) que les propriétés en C #. Et vous pouvez reproduire ce modèle même en C si vous le souhaitez.
Les propriétés en C # ne sont rien d'autre que du sucre syntaxique supporté par le langage.
la source