CodeGym /Cours /C# SELF /Erreurs avec les modificateurs d'accès et l'encapsulation...

Erreurs avec les modificateurs d'accès et l'encapsulation

C# SELF
Niveau 25, Leçon 2
Disponible

1. Introduction

Les modificateurs d'accès, c'est comme les clôtures et les serrures chez toi : ça définit qui peut entrer dans quelle pièce, et qui peut juste mater par le trou de la serrure. Rappel, en C#, t'as ces options :

Modificateur Qui voit
public
Tous
private
Seulement à l'intérieur de la classe courante
protected
Classe courante et héritiers
internal
Tout le projet (assembly)
protected internal
Tout le projet + héritiers
private protected
Seulement les héritiers dans ce même projet

Le but de l'encapsulation — c'est de cacher les détails d'implémentation de ta classe, pour que personne ne puisse ruiner ton objet avec une sale ligne genre obj.Field = 99999;, si t'as pas envie que ça arrive.

2. Erreurs classiques avec les niveaux d'accès

Tout ouvrir en public

L'erreur la plus courante — déclarer tous les champs et méthodes d'une classe en public. La logique c'est genre : "On sait jamais, ça peut servir ! Que les autres utilisent mes membres où ils veulent !". Ça a l'air pratique, jusqu'à ce que quelqu'un foute ton objet dans un état chelou, ou commence à utiliser tes trucs internes et que t'as la frousse de toucher au code.

Exemple d'erreur :


public class BankAccount
{
    public string Owner;
    public decimal Balance;
}

Maintenant n'importe qui peut faire ça :


var acc = new BankAccount();
acc.Owner = "";
acc.Balance = -1000000M; // Oups, une dette d'un million !

Qu'est-ce qui cloche ?
T'as cassé toutes les règles de sécurité et de bon sens. Même si ta banque ne contient que des feuilles d'arbre ou des billets Monopoly, un solde négatif "par envie" — c'est chelou.

Transformer une classe en "structure sans structure"

Deuxième erreur typique — rendre publics non seulement les champs, mais aussi les propriétés et méthodes internes qui devraient jamais sortir.


public class Vault
{
    public string DoorPIN = "1234";
    public void OpenDoor() 
    {
        // Un peu de magie
    }
}

Et maintenant ? Ben voilà : n'importe qui peut choper le PIN et ouvrir la porte de ton coffre. Même si c'est un "coffre de test", dans un mois quelqu'un oublie ce trou, et c'est la cata.

La bonne approche :
L'interface de ta classe doit être minimale et protégée. Ce qui doit être accessible aux autres — tu mets en public. Ce qui est juste pour toi — private. Si c'est pour les héritiers — protected.

3. Erreurs d'encapsulation

En .NET, c'est clair : aucune donnée de classe (état) ne doit être stockée dans des champs publics ! Tout doit être fermé ou au moins passé par des propriétés. Accès direct aux champs — c'est du mauvais style et une source de bugs bien galère à trouver.

Pourquoi les champs doivent être private

Les champs — c'est la base de l'état interne de l'objet. Si tu les rends publics, tu perds le contrôle sur quand et quelles valeurs peuvent y être mises. Ton objet devient vulnérable aux valeurs foireuses, et si tu changes leur format, tous les accès publics cassent.

À la place :
Déclare tes champs en private, et expose seulement les propriétés ou méthodes nécessaires :


public class BankAccount
{
    private decimal balance;

    public decimal Balance
    {
        get { return balance; }
        private set 
        {
            if (value < 0) 
                throw new ArgumentException("Le solde ne peut pas être négatif");
            balance = value;
        }
    }

    public BankAccount(decimal initialBalance)
    {
        Balance = initialBalance;
    }

    public void Deposit(decimal amount)
    {
        if (amount <= 0) throw new ArgumentException("Impossible de déposer zéro ou moins !");
        Balance += amount;
    }
}

Grosse erreur : public set pour des données qui ne doivent pas changer

Parfois, on a juste besoin du get, mais les devs mettent public { get; set; } "par défaut", parce que c'est plus rapide. Résultat, n'importe qui peut faire :


account.Balance = 99999999; // Pourquoi pas ?

Mieux comme ça :
Si la propriété doit être modifiée seulement dans la classe, mets un set avec modificateur :


public decimal Balance { get; private set; }

ou, si la valeur doit être fixée seulement à la création de l'objet (C# 14) :


public decimal Balance { get; init; }

4. Quand protected est aussi un piège

Des portes grandes ouvertes pour tous les héritiers

protected — c'est cool pour filer des fonctionnalités à l'héritier, mais certains trucs ne doivent même pas être accessibles aux héritiers ! Genre, si tes enfants (héritiers de la classe) ne doivent pas casser des champs critiques direct.

Exemple :


public class SecureVault
{
    protected string secretCode = "1234";
}

Maintenant, n'importe quel héritier peut faire :


public class HackerVault : SecureVault
{
    public void Hack()
    {
        secretCode = "0000"; // Secret changé easy !
    }
}

Recommandation :
Utilise protected seulement pour ce qui doit vraiment être accessible aux héritiers. Le reste, tu laisses en privé, et pour les opérations nécessaires, tu fais des méthodes protégées.

5. Erreurs avec internal et les assemblies mélangées

Le modificateur internal a l'air cool : "tout dispo dans le projet". Mais dès que le projet dépasse un fichier ou se connecte à des libs, ça part en vrille. Souvent, les étudiants rendent des trucs publics dans l'assembly alors que la classe devrait être totalement cachée.

Exemple :


internal class Logger
{
    internal void Write(string msg) { /* ... */ }
}

Maintenant, n'importe qui peut appeler Logger.Write depuis n'importe quel fichier du projet. Et si dans un an, quelqu'un branche ta DLL à un autre projet ? Toute la "cuisine interne" sera visible si t'as laissé des trucs en public.

Conseil :
Mets internal pour les classes techniques, mais garde les détails sensibles en private.

6. Pratique : appli bancaire

On continue avec notre exemple d'appli bancaire, pour voir en vrai comme c'est facile de se planter et comment corriger.

Exemple d'erreur n°1 : Champs publics


public class BankAccount
{
    public decimal Balance;
    public string Owner;
}

Problème : n'importe qui peut tout casser.

On corrige avec des propriétés


public class BankAccount
{
    private decimal _balance;
    private string _owner;

    public string Owner => _owner; // Lecture seule

    public decimal Balance 
    { 
        get => _balance; 
        private set 
        {
            if (value < 0) throw new ArgumentException("Le solde ne peut pas être négatif");
            _balance = value;
        }
    }

    public BankAccount(string owner, decimal initialBalance)
    {
        if (string.IsNullOrWhiteSpace(owner))
            throw new ArgumentException("Le nom du propriétaire est obligatoire");

        _owner = owner;
        Balance = initialBalance;
    }

    public void Deposit(decimal amount)
    {
        if (amount <= 0)
            throw new ArgumentException("Le montant du dépôt doit être positif");
        Balance += amount;
    }
}

Maintenant si tu tentes ça :


var acc = new BankAccount("Léna", 1000m);
acc.Balance = -700m; // Erreur ! set est privé.

Ou même ça :


acc.Owner = "Hacker"; // Erreur de compilation, pas de set

— ça marche pas. Seulement via le constructeur ou les méthodes.

Erreur : Propriétés "pour faire joli"

Beaucoup écrivent :


public int Age { get; set; }

Alors que l'âge devrait changer seulement via la méthode IncreaseAge (genre le 1er janvier), et pas direct.

7. Rappel visuel : ce qu'il ne faut pas faire et ce qu'il faut faire

graph TD
    A[Champs publics] -->|N'importe quel code| D[État incontrôlé]
    B[Champs privés + méthodes publiques] -->|Bien défini| E[État contrôlé]
    F[Setters publics] -->|N'importe qui peut changer| D
    G[Setters privés] -->|Seulement la classe| E
Approche État protégé ? On peut valider ? Facile à étendre ?
Champs publics ❌ ❌ ❌
Propriétés (get/set publics) ❌ Partiellement Oui, mais pas safe
Champs privés + propriété avec set privé ✅ ✅ ✅

8. Conseils de style pour bosser avec l'encapsulation

  • N'expose que ce qui est vraiment utile à l'utilisateur de la classe.
  • Valide toujours les données qui entrent dans l'objet.
  • Évite l'excès : si une propriété ne doit pas être modifiée de l'extérieur — mets le set en privé.
  • Pour la logique spéciale — utilise toujours des méthodes, pas l'accès direct.
  • Même si t'en as trop envie — ne fais pas de champs publics "pour tester".
  • Utilise des propriétés au lieu de champs directs même pour la lecture publique — c'est plus facile à faire évoluer après.
2
Mission
C# SELF, niveau 25, leçon 2
Bloqué
Erreurs liées aux niveaux d'accès et à l'encapsulation
Erreurs liées aux niveaux d'accès et à l'encapsulation
2
Mission
C# SELF, niveau 25, leçon 2
Bloqué
Implémentation de l'encapsulation et protection de l'état de la classe
Implémentation de l'encapsulation et protection de l'état de la classe
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION