Menu
Coddy logo textTech

Classes scellées

Fait partie de la section Programmation Orientée Objet du Journey C# de Coddy — leçon 22 sur 70.

Parfois, vous souhaitez arrêter la chaîne d'héritage. Le mot-clé sealed empêche une classe d'être héritée, verrouillant son implémentation afin qu'aucune autre classe ne puisse l'étendre.

public sealed class FinalDog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("Woof!");
    }
}

// Cela provoquerait une erreur de compilation :
// public class SuperDog : FinalDog { }

Pourquoi scelleriez-vous une classe ? La sécurité et l'intégrité de la conception sont des raisons courantes. Lorsque vous avez soigneusement conçu une classe et que vous ne voulez pas que quiconque modifie son comportement par héritage, le fait de la sceller garantit que votre implémentation reste intacte.

Vous pouvez également sceller des méthodes individuelles plutôt que des classes entières. Cela empêche toute redéfinition ultérieure tout en permettant à la classe elle-même d'être héritée :

public class Dog : Animal
{
    public sealed override void Speak()
    {
        Console.WriteLine("Woof!");
    }
}

public class Puppy : Dog
{
    // Impossible de surcharger Speak() - elle est scellée (sealed)
    // Mais on peut ajouter de nouvelles méthodes
    public void Whimper()
    {
        Console.WriteLine("Whimper...");
    }
}

Notez que sealed sur une méthode doit être combiné avec override. Vous ne pouvez sceller une méthode que si elle était déjà virtuelle dans une classe parente. Cela vous donne un contrôle précis : autorisez une certaine personnalisation dans la hiérarchie d'héritage, puis verrouillez-la à un point précis.

challenge icon

Défi

Facile

Construisons un système de traitement des paiements qui démontre comment utiliser sealed pour verrouiller les implémentations critiques. Vous allez créer une hiérarchie où certaines méthodes de paiement peuvent être étendues, mais les plus sécurisées sont scellées pour empêcher toute modification.

Vous allez créer quatre fichiers pour organiser votre code :

  • PaymentMethod.cs : Définissez une classe PaymentMethod dans l'espace de noms Payments. Cette classe de base possède une propriété Name (string) et un constructeur qui la définit. Incluez une méthode virtual appelée ProcessPayment(decimal amount) qui retourne "Processing ${amount} via {Name}".
  • CreditCardPayment.cs : Définissez une classe CreditCardPayment dans l'espace de noms Payments qui hérite de PaymentMethod. Ajoutez une propriété CardNumber (string). Le constructeur accepte le nom et le numéro de carte, en utilisant base pour transmettre le nom. Surchargez ProcessPayment avec le mot-clé sealed afin qu'aucune classe dérivée ultérieure ne puisse modifier ce comportement. Elle doit retourner "Charging ${amount} to card ending in {last 4 digits of CardNumber}".
  • BankTransfer.cs : Définissez une classe sealed appelée BankTransfer dans l'espace de noms Payments qui hérite de PaymentMethod. Cette classe entière est scellée - personne ne peut en hériter. Ajoutez une propriété BankName (string). Le constructeur accepte le nom et le nom de la banque. Surchargez ProcessPayment pour retourner "Transferring ${amount} from {BankName}".
  • Program.cs : Dans votre fichier principal, créez des instances des trois types de paiement en utilisant les valeurs d'entrée. Stockez-les en tant que références PaymentMethod et appelez ProcessPayment sur chacune pour démontrer le polymorphisme avec des implémentations scellées.

Vous recevrez quatre entrées :

  • Numéro de carte de crédit (16 chiffres)
  • Nom de la banque
  • Montant du paiement

Affichez le résultat du traitement d'un paiement par chaque méthode :

{base PaymentMethod result}
{CreditCardPayment result}
{BankTransfer result}

Par exemple, si les entrées sont 1234567890123456, First National, et 150.00, la sortie devrait être :

Processing $150.00 via Generic
Charging $150.00 to card ending in 3456
Transferring $150.00 from First National

Utilisez "Generic" comme nom pour l'instance de base PaymentMethod, "Credit Card" pour le paiement par carte de crédit, et "Bank Transfer" pour le virement bancaire.

La méthode scellée dans CreditCardPayment garantit que si quelqu'un crée une sous-classe, il ne peut pas modifier la façon dont les paiements par carte de crédit sont traités. La classe scellée BankTransfer empêche tout héritage - les deux sont des modèles de sécurité importants dans les systèmes de paiement !

Aide-mémoire

Le mot-clé sealed empêche une classe d'être héritée ou une méthode d'être redéfinie plus loin dans la chaîne d'héritage.

Sceller une classe :

public sealed class FinalDog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("Woof!");
    }
}

// This would cause a compile error:
// public class SuperDog : FinalDog { }

Les classes scellées sont utilisées pour la sécurité et l'intégrité de la conception, garantissant que l'implémentation ne peut pas être modifiée par héritage.

Sceller une méthode :

public class Dog : Animal
{
    public sealed override void Speak()
    {
        Console.WriteLine("Woof!");
    }
}

public class Puppy : Dog
{
    // Cannot override Speak() - it's sealed
    // But can add new methods
    public void Whimper()
    {
        Console.WriteLine("Whimper...");
    }
}

Le mot-clé sealed sur une méthode doit être combiné avec override. Vous ne pouvez sceller que des méthodes qui étaient déjà virtual dans une classe parente. Cela permet une personnalisation jusqu'à un point spécifique de la hiérarchie, puis la verrouille.

Essayez vous-même

using System;
using Payments;

class Program
{
    public static void Main(string[] args)
    {
        // Lire les entrées
        string cardNumber = Console.ReadLine();
        string bankName = Console.ReadLine();
        decimal amount = Convert.ToDecimal(Console.ReadLine());
        
        // TODO: Créer une instance de base PaymentMethod avec le nom "Generic"
        // La stocker en tant que référence PaymentMethod
        
        // TODO: Créer une instance CreditCardPayment avec le nom "Credit Card" et le numéro de carte
        // La stocker en tant que référence PaymentMethod
        
        // TODO: Créer une instance BankTransfer avec le nom "Bank Transfer" et le nom de la banque
        // La stocker en tant que référence PaymentMethod
        
        // TODO: Appeler ProcessPayment sur chacune et afficher les résultats
        // Chaque résultat doit être sur sa propre ligne
    }
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet