Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.
semantique_d_entite [2014/12/08 11:36] gbdivers |
semantique_d_entite [2018/07/20 23:36] (Version actuelle) winjerome Ajout du lien vers la chapitre suivant |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | ^ Chapitre précédent ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ Chapitre suivant ^ | + | ^ Chapitre précédent ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[heritage|Chapitre suivant]] ^ |
====== La sémantique d'entité ====== | ====== La sémantique d'entité ====== | ||
- | Jusque maintenant, on a vu qu'une seule sémantique, la sémantique de valeur. Pourquoi ? Principalement parce que la bibliothèque standard contient majoritairement des classes à sémantique de valeur. Les classes à sémantiques d'entités seront plus utilisée dans le code métier. | + | Jusque maintenant, on a vu qu'une seule sémantique, la sémantique de valeur. Pourquoi ? Principalement parce que la bibliothèque standard contient majoritairement des classes à sémantique de valeur. Les classes à sémantiques d'entités seront plus utilisées dans le code métier. |
+ | |||
+ | Cette sémantique impose des contraintes sur l'interface des classes, ce que l'on pourrait voir comme une limitation, mais cette sémantique est compatible avec un concept important en programmation orientée objet : l'héritage (qui sera vu dans le chapitre suivant). | ||
===== Critère d'unicité ===== | ===== Critère d'unicité ===== | ||
- | A quoi correspond la sémantique d'entité ? Aux objets comme on le conçoit habituellement. Prennons pas exemple une table et de chaises. Chaque objet est //unique//, deux chaises ont beau être identique, ce sont bien deux objets différents. Quoi que l'on fasse avec les chaises (sauf les détruire...), les chaises restent individualisables. C'est le principal critère de la sémantique d'entité : l'unicité. | + | A quoi correspond la sémantique d'entité ? Aux objets comme on le conçoit habituellement. Prenons pas exemple une table et de chaises. Chaque objet est //unique//, deux chaises ont beau être identique, ce sont bien deux objets différents. Quoi que l'on fasse avec les chaises (sauf les détruire...), les chaises restent individualisables. C'est le principal critère de la sémantique d'entité : l'unicité. |
- | A contraire, la sémantique de valeur ne reconnait pas cette unicité. Par exemple, si on considère la valeur "5", que l'on entre directement cette valeur dans le code, que cette valeur soit le résultat d'un calcul ou le retour d'une fonction, la valeur est toujours la même, il n'est pas possible de distinguer la valeur "5" provenant de l'une ou l'autre moyen de la créer. | + | Au contraire, la sémantique de valeur ne reconnait pas cette unicité. Par exemple, si on considère la valeur "5", que l'on entre directement cette valeur dans le code, que cette valeur soit le résultat d'un calcul ou le retour d'une fonction, la valeur est toujours la même, il n'est pas possible de distinguer la valeur "5" provenant de l'une ou l'autre moyen de la créer. |
<code cpp> | <code cpp> | ||
Ligne 18: | Ligne 20: | ||
</code> | </code> | ||
- | Pour prendre un exemple issu de l'univers informatique, prenons par exemple les fenêtres d'un système. Chaque fenêtre est individualisable, en général pour leur position et leur dimensions. Même si deux fenêtres semblent identiques en tous points, il reste possible de les déplacer séparément, d'en fermer une seule, etc. Ce sont bien des entités, au sens "objet unique". | + | Pour prendre un exemple issu de l'univers informatique, prenons par exemple les fenêtres d'un système. Chaque fenêtre est individualisable, en général par leur position et leur dimensions. Même si deux fenêtres semblent identiques en tous points, il reste possible de les déplacer séparément, d'en fermer une seule, etc. Ce sont bien des entités, au sens "objet unique". |
- | En termes de code, cela signifie que l'on va pouvoir écrire : | + | En terme de code, cela signifie que l'on va pouvoir écrire : |
<code cpp> | <code cpp> | ||
Ligne 83: | Ligne 85: | ||
Idem pour le destructeur, si on n'en fournit pas, le compilateur proposera un destructeur par défaut. | Idem pour le destructeur, si on n'en fournit pas, le compilateur proposera un destructeur par défaut. | ||
- | Le plus souvent, ces constructeurs et destructeur seront publiques, mais il peut être intéressant de les mettre en privée. Dans ce cas, il ne sera pas possible de créer ces objets directement en appelant le constructeur. On pourra alors créer par exemple une fonction (ou classe) dédiée pour la création des objets (voir le design pattern factory). Il faudra alors mettre cette fonction (ou classe) en ''friend'' pour qu'elle soit autorisée à accéder aux membres privés. | + | Le plus souvent, ces constructeurs et destructeur seront publics, mais il peut être intéressant de les mettre en privé. Dans ce cas, il ne sera pas possible de créer ces objets directement en appelant le constructeur. On pourra alors créer par exemple une fonction (ou classe) dédiée pour la création des objets (voir le design pattern //factory//). Il faudra alors mettre cette fonction (ou classe) en ''friend'' pour qu'elle soit autorisée à accéder aux membres privés. |
<code cpp> | <code cpp> | ||
Ligne 96: | Ligne 98: | ||
==== Copie et clonage ==== | ==== Copie et clonage ==== | ||
+ | |||
+ | L'une des conséquences de la sémantique d'entité est qu'il n'est pas possible de copier un objet. Il faut donc obligatoirement désactiver le constructeur par copie et l'opérateur par copie, pour éviter que le compilateur les créés. | ||
+ | |||
+ | <code cpp> | ||
+ | class MyClass { | ||
+ | public: | ||
+ | MyClass(MyClass const&) = delete; | ||
+ | MyClass& operator=(MyClass const&) = delete; | ||
+ | }; | ||
+ | </code> | ||
+ | |||
+ | Concernant la sémantique de déplacement, il n'y a pas d'obligation de la désactiver. Cela va dépendre de la sémantique que vous souhaitez donner à votre classe. | ||
+ | |||
+ | <note info>L'explication de pourquoi il n'est pas possible de copier une classe à sémantique d'entité est lié à l'héritage et l'impossibilité de créer un constructeur virtuel. Vous verrez dans le prochain chapitre ces notions et le pourquoi, pour le moment, accepter cette idée telle quelle.</note> | ||
+ | |||
+ | ==== Opérateurs de comparaison ==== | ||
+ | |||
+ | De la même façon, cela n'a pas de sens de comparer des classes à sémantiques d'entité, puisque par définition, tous les objets sont différents. Cela n'a donc pas de sens de vouloir par exemple déterminer quel objet est supérieur à un autre. Par contre, il est possible de comparer les objets selon d'un de ses membres qui serait à sémantique de valeur. Par exemple, les chaises peuvent être comparées selon leur poids ou leur taille, les fenêtres peuvent être comparées selon leur position ou leur dimension. | ||
+ | |||
+ | <code cpp> | ||
+ | widget w1, w2; | ||
+ | |||
+ | std::cout << std::boolalpha; | ||
+ | std::cout << (w1 > w2) << std::endl; // n'a pas de sens | ||
+ | std::cout << (w1.x > w2.x) << std::endl; // ok | ||
+ | </code> | ||
+ | |||
+ | De la même façon, cela n'a pas de sens de tester l'égalité ou la différence avec la sémantique d'entité, puisque par définition les entités sont uniques. Elles ne peuvent être égale qu'à elles mêmes et différentes dans tous les autres cas. | ||
+ | |||
+ | <code cpp> | ||
+ | widget w1, w2; | ||
+ | |||
+ | std::cout << std::boolalpha; | ||
+ | std::cout << (w1 == w2) << std::endl; // n'a pas de sens, puisque toujours faux | ||
+ | std::cout << (w1 == w1) << std::endl; // n'a pas de sens, puisque toujours vrai | ||
+ | std::cout << (w1 != w2) << std::endl; // n'a pas de sens, puisque toujours vrai | ||
+ | </code> | ||
+ | <note info>On pourrait penser que puisque ces tests ne posent pas de problèmes particuliers, on pourrait quand même les conserver, même s'ils retournent un résultat prévisible. En pratique, avec la notion d'héritage que vous verrez dans le prochain chapitre, l'implémentation de ces fonctions n'est pas trivial. Il est donc pertinent de les désactiver, pour éviter les problèmes de comparaison que poserait les fonctions créées par défaut par le compilateur. | ||
+ | Il sera parfois intéressant de pouvoir quand même tester l'unicité des entités, mais cette problématique ne sera pas forcement simple. Nous reviendrons sur ce problème dans un prochain chapitre.</note> | ||
+ | ==== Opérateurs arithmétiques ==== | ||
+ | Pour la même raison que les opérateurs de comparaison, cela n'a pas de sens de définir les opérateurs arithmétiques sur des entités. Seuls les membres à sémantiques de valeur pourraient avoir des opérateurs arithmétiques. | ||
+ | ===== Conclusion ===== | ||
+ | On voit que les classes à sémantique d'entité interdisent de nombreuses fonctions de base que l'on a rencontré dans les classes à sémantiques de valeur (redéfinir des opérateurs de comparaison ou des opérateurs arithmétiques). L'intérêt de cette sémantique sera qu'elle autorise l'héritage de classe, que nous allons voir dans le prochain chapitre. | ||
- | ^ Chapitre précédent ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ Chapitre suivant ^ | + | ^ Chapitre précédent ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[heritage|Chapitre suivant]] ^ |
{{tag> Cours C++}} | {{tag> Cours C++}} |