Aller au contenu principal

Classes et objets

Notions théoriques

Anatomie d'une classe C#

Une classe regroupe des champs (données internes), des propriétés (accès contrôlé aux données) et des méthodes (comportements).

class Etudiant
{
// Champ privé — préfixe _ par convention
private double _note;

// Propriétés publiques (accès contrôlé)
public string Nom { get; set; } = "";
public int Age { get; set; }
public double Note
{
get => _note;
set => _note = (value >= 0 && value <= 20) ? value : _note; // validation
}

// Méthode publique — comportement
public string ObtenirMention() => Note switch
{
>= 16 => "Très bien",
>= 14 => "Bien",
>= 12 => "Assez bien",
>= 10 => "Passable",
_ => "Insuffisant",
};

// Surcharge de ToString() pour l'affichage
public override string ToString()
=> $"Etudiant({Nom}, {Age} ans, {Note:F1}/20)";
}

Champs privés — convention _underscore

En C#, les champs privés utilisent conventionnellement un préfixe _ (underscore) pour les distinguer des paramètres et propriétés :

class Compte
{
private decimal _solde; // champ privé : _solde
private string _titulaire; // champ privé : _titulaire

public decimal Solde => _solde; // propriété en lecture seule
public string Titulaire => _titulaire;

public void Deposer(decimal montant)
{
if (montant <= 0)
throw new ArgumentException("Le montant doit être positif.");
_solde += montant;
}
}

Membres statiques — partagés par toutes les instances

Un membre statique appartient à la classe, pas à un objet particulier. Toutes les instances partagent la même valeur.

class Etudiant
{
// Champ statique — partagé par tous les étudiants
private static int _nombreTotal = 0;

public string Nom { get; set; } = "";

public Etudiant(string nom)
{
Nom = nom;
_nombreTotal++; // incrémenté à chaque création
}

// Propriété statique — accessible sans instance
public static int NombreTotal => _nombreTotal;
}

var a = new Etudiant("Alice");
var b = new Etudiant("Bob");
Console.WriteLine(Etudiant.NombreTotal); // 2 — on accède via le nom de la classe

Surcharger ToString()

ToString() est appelée automatiquement lors d'un affichage (Console.WriteLine(obj) ou interpolation $"{obj}"). On la surcharge avec override :

class Produit
{
public string Nom { get; set; } = "";
public decimal Prix { get; set; }

public override string ToString()
=> $"{Nom} ({Prix:F2} €)";
}

var p = new Produit { Nom = "Clavier", Prix = 49.99m };
Console.WriteLine(p); // "Clavier (49.99 €)"
Console.WriteLine($"Produit : {p}"); // "Produit : Clavier (49.99 €)"

Classe statique — utilitaires purs

Une classe statique ne peut pas être instanciée. Elle ne contient que des méthodes statiques (utilitaires).

static class Calculateur
{
public static double Moyenne(double[] notes)
=> notes.Length == 0 ? 0 : notes.Average();

public static string Mention(double note) => note switch
{
>= 16 => "Très bien",
>= 10 => "Passable",
_ => "Insuffisant",
};
}

double moy = Calculateur.Moyenne([15.5, 12.0, 9.5]);
Console.WriteLine(Calculateur.Mention(moy));

Exemple pratique

class Produit
{
private static int _prochainId = 1;

public int Id { get; }
public string Nom { get; set; } = "";
public decimal Prix { get; set; }
public int Stock { get; private set; }

public static int NombreProduits => _prochainId - 1;

public Produit(string nom, decimal prix, int stockInitial)
{
Id = _prochainId++;
Nom = nom;
Prix = prix;
Stock = stockInitial;
}

public bool Vendre(int quantite)
{
if (quantite <= 0 || quantite > Stock)
return false;
Stock -= quantite;
return true;
}

public void Reapprovisionner(int quantite)
{
if (quantite > 0)
Stock += quantite;
}

public override string ToString()
=> $"[{Id:D3}] {Nom,-20} {Prix,8:F2} € | Stock : {Stock,4}";
}

// Utilisation
var produits = new List<Produit>
{
new Produit("Clavier mécanique", 69.99m, 5),
new Produit("Souris ergonomique", 49.99m, 0),
new Produit("Câble USB-C", 9.99m, 12),
};

Console.WriteLine("=== Catalogue ===");
foreach (var p in produits)
Console.WriteLine(p);

Console.WriteLine($"\nNombre de produits : {Produit.NombreProduits}");

// Opérations
produits[0].Vendre(2);
produits[1].Reapprovisionner(10);

Console.WriteLine("\n=== Après opérations ===");
foreach (var p in produits)
Console.WriteLine(p);

Test de mémorisation/compréhension


Quelle convention de nommage s'applique aux champs privés en C# ?


Comment appelle-t-on un membre qui appartient à la classe entière (pas à une instance) ?


Comment accède-t-on à un membre statique ?


Quel mot-clé permet de redéfinir la méthode `ToString()` héritée ?


Quelle est la particularité d'une classe statique ?


TP pour réfléchir et résoudre des problèmes

Vous allez créer une classe CompteBancaire avec des membres privés et statiques.

Étape 1 — Définir la classe avec un compteur statique

Créez la classe avec un identifiant auto-incrémenté.


Bonne pratique - Exposer les données via des propriétés, pas des champs

Le champ _solde est privé : personne ne peut le modifier directement de l'extérieur. On expose la valeur en lecture seule via public decimal Solde => _solde. Pour modifier le solde, il faut passer par les méthodes Deposer et Retirer qui peuvent appliquer des règles métier (ex: refuser un montant négatif).

Étape 2 — Ajouter les méthodes Deposer et Retirer

Implémentez les opérations bancaires avec validation.


Bonne pratique - Retourner bool pour les opérations qui peuvent échouer

Retirer retourne bool plutôt que de lever une exception, car un solde insuffisant est une situation normale (pas une erreur de programmation). L'appelant peut tester le résultat : if (!compte.Retirer(500m)) Console.WriteLine("Solde insuffisant.");. Les exceptions sont réservées aux erreurs vraiment inattendues.

Étape 3 — Surcharger ToString et tester

Ajoutez ToString() et créez plusieurs comptes pour tester.


Bonne pratique - ToString() lisible pour le débogage

Une bonne implémentation de ToString() rend le débogage beaucoup plus facile. Quand vous mettez un point d'arrêt dans un IDE (Visual Studio, Rider), la valeur affichée dans l'inspecteur de variables est celle de ToString(). Un affichage comme "Compte #0001 | Alice Martin | Solde : 1250.00 €" est immédiatement lisible.

📌 Une solution