Chapitre 417 minIntermédiaire
Diagramme de classes : attributs, opérations, visibilité et multiplicités
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- dessiner une classe avec ses attributs typés et ses opérations ;
- choisir la bonne visibilité pour chaque membre ;
- poser et lire les multiplicités d'une association ;
- trouver les classes et les associations dans un texte.
4 exercices corrigés2 schémas
Le diagramme de classes représente la structure d'un logiciel orienté objet : ses classes, avec leurs attributs et leurs opérations, et les relations entre ces classes. C'est le diagramme UML le plus utilisé, celui qui se traduit directement en code et celui que les sujets d'examen fournissent le plus souvent. Ce chapitre présente la notation d'une classe, la visibilité, les associations et la lecture des multiplicités ; le chapitre 5 traite l'héritage, la composition, l'agrégation et les interfaces.
Classe et objet
Une classe décrit un ensemble d'objets qui ont la même structure et le même comportement : la classe FicheFrais décrit toutes les fiches de frais. Un objet (ou instance) est un exemplaire précis : la fiche de novembre 2026 de Lucas Moreau. La classe est le moule, l'objet est le gâteau. Le diagramme de classes montre les moules ; le diagramme d'objets (chapitre 10) montre des gâteaux à un instant donné.
Les notions de classe, d'objet, d'encapsulation et de constructeur sont expliquées en détail, code à l'appui, dans le cours Programmation orientée objet (classe et objet, encapsulation). Ce chapitre se concentre sur la façon de les dessiner.
La notation d'une classe
Une classe se dessine par un rectangle à trois compartiments :
- le nom, au singulier, en UpperCamelCase (
FicheFrais,LigneFraisHorsForfait), centré et en gras ; - les attributs, les données que chaque objet porte ;
- les opérations, ce que chaque objet sait faire.
On n'est pas obligé de tout montrer. Selon le moment du projet, une classe peut se réduire à son nom (diagramme d'esquisse, vue d'ensemble), montrer ses attributs sans types (analyse), ou tout détailler (conception, avant le code). Un compartiment vide n'affirme rien : il dit seulement qu'on ne montre rien ici.
Les attributs
La syntaxe complète d'un attribut est :
visibilité nom : Type [multiplicité] = valeurInitiale {propriétés}
Seul le nom est obligatoire ; en conception, on donne au moins la visibilité, le nom et le type.
| Exemple | Signification |
|---|---|
- mois : string | Attribut privé mois, de type chaîne |
- etat : EtatFiche = Creee | Attribut privé, dont la valeur initiale est Creee |
- montantValide : decimal [0..1] | Attribut facultatif : il n'a pas de valeur tant que la fiche n'est pas validée |
- telephones : string [1..3] | Un à trois numéros de téléphone |
/ total : decimal | Attribut dérivé, calculé à partir d'autres (somme des lignes) : il n'est pas stocké |
- id : int {readOnly} | Attribut qui ne change plus après sa création |
- nbFiches : int, souligné | Attribut de classe (statique), partagé par tous les objets |
Pour les types, UML définit quelques types primitifs (Integer, Real, Boolean, String), mais les diagrammes de conception utilisent presque toujours ceux du langage visé : int, decimal, bool, string, DateOnly en C#. Les sujets d'examen font de même, parfois avec des types génériques (Entier, Chaîne, Date) : reprends les types du sujet.
Les opérations
La syntaxe d'une opération est :
visibilité nom(paramètre : Type, …) : TypeRetour
| Exemple | Signification |
|---|---|
+ Cloturer() | Opération publique sans paramètre ni valeur de retour |
+ Valider(comptable : Comptable) | Un paramètre de type Comptable |
+ TotalForfait() : decimal | Renvoie un decimal |
- VerifierEtat(attendu : EtatFiche) | Opération privée, utilisée par les autres opérations de la classe |
+ FicheFrais(mois : string, visiteur : Visiteur) | Un constructeur : même nom que la classe (on voit aussi le stéréotype «create») |
+ Role() : string, en italique | Opération abstraite, sans code dans cette classe (chapitre 5) |
+ Creer(…) : FicheFrais, souligné | Opération de classe (statique) |
En général, on ne dessine ni les accesseurs (getMois(), setMois()) ni les propriétés C# triviales : ils alourdissent le diagramme sans rien apprendre. On ne montre que les opérations qui portent une logique métier.
La visibilité
La visibilité dit qui a le droit d'utiliser un attribut ou une opération. C'est la traduction graphique de l'encapsulation : en règle générale, les attributs sont privés et les opérations utiles aux autres classes sont publiques.
| Symbole | Visibilité UML | Qui y a accès | En C# |
|---|---|---|---|
+ | publique (public) | Tout le monde | public |
- | privée (private) | La classe elle-même | private |
# | protégée (protected) | La classe et ses sous-classes | protected |
~ | paquetage (package) | Les classes du même paquetage | Pas d'équivalent exact ; internal (même assembly) est le plus proche |
Les associations
Une association est une relation durable entre deux classes : leurs objets se connaissent. Elle se dessine par un trait plein entre les deux classes et peut porter :
- un nom, au milieu, souvent un verbe, avec un petit triangle qui donne le sens de lecture : « Visiteur — remplit ▸ — FicheFrais » ;
- un rôle à chaque extrémité, qui dit ce que représente l'objet du bout pour celui d'en face :
validateurdu côté deComptable(pour une fiche, ce comptable est son validateur) ; - une multiplicité à chaque extrémité ;
- une navigabilité, une flèche ouverte au bout du trait.
Les multiplicités
La multiplicité écrite à une extrémité d'une association dit combien d'objets de cette classe sont reliés à un objet de la classe d'en face.
| Multiplicité | Lecture |
|---|---|
1 | Exactement un |
0..1 | Zéro ou un |
* ou 0..* | Zéro ou plusieurs (aucune limite) |
1..* | Au moins un |
2..5 | De deux à cinq |
3 | Exactement trois |
La règle de lecture : pars d'un objet de la classe A, traverse le trait, lis le nombre écrit près de B.
Sur cet exemple :
- un visiteur remplit
0..*fiches : zéro le jour de son embauche, puis une par mois ; - une fiche est remplie par
1visiteur, toujours, et par un seul.
Trouver la bonne multiplicité
Pour chaque extrémité, pose deux questions : « Au minimum, combien ? » (0 ou 1, rarement plus) et « Au maximum, combien ? » (1 ou plusieurs). Le minimum dépend des règles de gestion et du moment de la vie de l'objet : une fiche peut-elle exister sans visiteur, même une seconde ? Non : minimum 1. Un visiteur peut-il exister sans fiche ? Oui, le jour de son arrivée : minimum 0.
La navigabilité
Par défaut, une association se parcourt dans les deux sens : la fiche connaît son visiteur, le visiteur connaît ses fiches. Une flèche ouverte au bout du trait restreint le parcours : FicheFrais ──▸ FraisForfait dit qu'une fiche connaît les forfaits qu'elle utilise, mais qu'un forfait ne connaît pas les fiches qui l'utilisent. Une croix au bout du trait dit explicitement « non navigable dans ce sens ».
La navigabilité est une décision de conception, qui se lit directement dans le code : seule la classe d'où part la flèche possède une référence vers l'autre (chapitre 6). En analyse, on la laisse souvent de côté ; en conception, elle évite des références inutiles et des dépendances croisées.
L'association réflexive
Une association réflexive relie une classe à elle-même. Les rôles deviennent alors indispensables pour savoir qui est qui. Chez GSB, chaque visiteur peut avoir un responsable de secteur, lui-même visiteur :
Visiteur "0..1 responsable" ──── "0..* equipe" Visiteur
Se lit : un visiteur a zéro ou un responsable ; un visiteur (en tant que responsable) a zéro ou plusieurs visiteurs dans son équipe.
Trouver les classes dans un texte
Devant un cahier des charges, la méthode classique est l'analyse grammaticale :
- Souligne les noms : ce sont les classes candidates, ou leurs attributs.
- Élimine les noms vagues (« système », « information »), les synonymes (« note de frais » et « fiche de frais » sont la même chose), les acteurs qui n'ont pas de données à mémoriser, et les noms qui ne sont qu'une valeur (« montant », « date », « libellé » : ce sont des attributs).
- Garde comme classe ce qui a une identité, plusieurs propriétés et une vie propre : un visiteur, une fiche, une ligne de frais, un forfait.
- Repère les verbes qui relient deux classes (« un visiteur remplit une fiche ») : ce sont des associations. Les verbes qui décrivent un traitement (« le comptable valide la fiche ») deviennent des opérations, souvent de la classe qui subit l'action ou qui possède les données (
FicheFrais.Valider()). - Pose les multiplicités en relisant les règles de gestion, phrase par phrase.
Appliquée au cahier des charges d'AppliFrais, la méthode donne les classes Visiteur, Comptable, Region, FicheFrais, FraisForfait (les quatre forfaits et leur montant), LigneFraisForfait (une quantité d'un forfait sur une fiche) et LigneFraisHorsForfait. Le diagramme complet est au chapitre 5, une fois l'héritage et la composition présentés.
Exercices
Exercice 1 sur 4 Lire une classe Réussi À revoir
Voici une classe d'un sujet :
Abonnement
- numero : string {readOnly}
- dateDebut : Date
- dureeMois : int = 12
- / dateFin : Date
- nbAbonnements : int (souligné)
+ Abonnement(numero : string, dateDebut : Date)
+ Renouveler(mois : int)
+ EstActif(jour : Date) : bool
- CalculerFin() : Date
- Que signifient
{readOnly},= 12, la barre oblique devantdateFinet le soulignement denbAbonnements? - Quelle opération est un constructeur ? Laquelle renvoie une valeur ?
- Pourquoi
CalculerFin()est-elle privée ?
Voir la réponseMasquer la réponse de l'exercice 1
{readOnly}: le numéro ne change plus après la création.= 12: valeur initiale, un abonnement dure 12 mois par défaut./ dateFin: attribut dérivé, calculé à partir dedateDebutetdureeMois, pas stocké. Le soulignement :nbAbonnementsest un attribut de classe (statique), un compteur partagé par tous les abonnements.Abonnement(numero, dateDebut)est le constructeur (même nom que la classe).EstActif(jour)renvoie un booléen,CalculerFin()une date.- C'est un détail interne, utilisé par la classe elle-même (sans doute pour obtenir
dateFin). Les autres classes n'ont pas à l'appeler : on l'encapsule.
Tu avais trouvé ?
Exercice 2 sur 4 Écrire les multiplicités Réussi À revoir
Pour chaque règle de gestion, dessine l'association (en texte, au format ClasseA "multiplicité" ──── "multiplicité" ClasseB).
- Un adhérent emprunte au plus 5 livres à la fois ; un livre est emprunté par au plus un adhérent à la fois.
- Une commande contient au moins un produit ; un produit figure dans un nombre quelconque de commandes.
- Un salarié dispose d'au plus une voiture de fonction ; une voiture de fonction est attribuée à exactement un salarié.
- Une équipe de football aligne exactement 11 joueurs titulaires ; un joueur est titulaire dans une seule équipe.
Voir la réponseMasquer la réponse de l'exercice 2
Adherent "0..1" ──── "0..5" Livre. Le0..5près de Livre se lit « un adhérent emprunte 0 à 5 livres » ; le0..1près d'Adherent, « un livre est emprunté par 0 ou 1 adhérent ».Commande "0..*" ──── "1..*" Produit. Près de Produit : une commande contient au moins un produit. Près de Commande : un produit est dans zéro ou plusieurs commandes.Salarie "1" ──── "0..1" VoitureFonction.Equipe "1" ──── "11" Joueur. Un exemple rare de multiplicité exacte supérieure à 1.
Tu avais trouvé ?
Exercice 3 sur 4 Trouver les erreurs Réussi À revoir
Un étudiant a dessiné la classe suivante pour une application de gestion de tickets d'assistance :
Ticket
+ id : int
+ titre : string
+ idTechnicien : int
+ technicien : Technicien
+ getTitre() : string
+ setTitre(t : string)
+ Cloturer()
Il a aussi tracé une association entre Ticket et Technicien. Relève quatre défauts.
Voir la réponseMasquer la réponse de l'exercice 3
- Les attributs sont publics (
+) : ils devraient être privés (-), l'encapsulation l'exige. idTechnicienest une clé étrangère : une idée de base de données, sans place dans un diagramme de classes.technicien : Technicienfait doublon avec l'association tracée versTechnicien: il faut garder l'association et retirer l'attribut.getTitre()etsetTitre()sont des accesseurs triviaux : on ne les dessine pas en général. SeuleCloturer(), qui porte une règle métier, mérite d'apparaître.
On peut aussi discuter de id : utile si l'application l'affiche ou s'en sert pour retrouver un ticket, mais ce n'est pas lui qui distingue deux objets en mémoire.
Tu avais trouvé ?
Exercice 4 sur 4 Du texte au diagramme Réussi À revoir
« Une auto-école propose des leçons de conduite. Chaque leçon a une date, une heure de début et une durée, et elle est donnée par un moniteur à un élève, dans un véhicule. Un élève suit autant de leçons qu'il veut ; un moniteur en donne plusieurs par jour. Chaque véhicule a une immatriculation, une marque et un type de boîte (manuelle ou automatique). Un élève a un nom, un prénom et un numéro de livret. Un moniteur a un nom, un prénom et un numéro d'agrément. »
Donne les classes avec leurs attributs typés, puis les associations avec leurs multiplicités.
Voir la réponseMasquer la réponse de l'exercice 4
Classes
Eleve:- nom : string,- prenom : string,- numeroLivret : stringMoniteur:- nom : string,- prenom : string,- numeroAgrement : stringVehicule:- immatriculation : string,- marque : string,- boite : TypeBoiteLecon:- date : DateOnly,- heureDebut : TimeOnly,- dureeMinutes : int«enumeration» TypeBoite:Manuelle,Automatique
Associations
Lecon "0..*" ──── "1" Eleve: une leçon est suivie par un élève ; un élève suit zéro ou plusieurs leçons.Lecon "0..*" ──── "1" Moniteur: une leçon est donnée par un moniteur ; un moniteur donne zéro ou plusieurs leçons.Lecon "0..*" ──── "1" Vehicule: une leçon se déroule dans un véhicule ; un véhicule sert à zéro ou plusieurs leçons.
La leçon est une classe à part entière, reliée aux trois autres, et non un attribut de l'élève : elle a ses propres attributs et se répète. Le type de boîte, qui ne prend que deux valeurs, devient une énumération. On aurait pu factoriser nom et prenom dans une classe mère Personne : c'est l'objet du chapitre suivant.
Tu avais trouvé ?