Interfaces Multiples
Fait partie de la section Programmation Orientée Objet du Journey C# de Coddy — leçon 27 sur 70.
Alors qu'une classe ne peut hériter que d'une seule classe de base, elle peut implémenter autant d'interfaces que nécessaire. C'est l'un des avantages clés des interfaces par rapport aux classes abstraites : elles permettent à une classe d'adopter plusieurs comportements.
Pour implémenter plusieurs interfaces, il suffit de les lister après les deux-points, séparées par des virgules :
public interface IFlyable
{
void Fly();
}
public interface ISwimmable
{
void Swim();
}
public class Duck : IFlyable, ISwimmable
{
public void Fly()
{
Console.WriteLine("Flying through the air");
}
public void Swim()
{
Console.WriteLine("Swimming in the pond");
}
}La classe Duck doit implémenter tous les membres des deux interfaces. Cela modélise naturellement des scénarios du monde réel - un canard peut véritablement à la fois voler et nager, il est donc logique qu'il remplisse les deux contrats.
Lorsque vous combinez l'héritage avec plusieurs interfaces, la classe de base doit être placée en premier :
public class Duck : Bird, IFlyable, ISwimmable
{
// Hérite de Bird, implémente les deux interfaces
}Cette flexibilité vous permet de composer des comportements à partir de plusieurs sources. Un Robot pourrait implémenter IMovable, IChargeable et ISpeakable. Chaque interface représente une capacité unique, et votre classe peut combiner exactement ce dont elle a besoin.
Défi
FacileConstruisons un système d'appareils domestiques intelligents qui démontre comment une seule classe peut implémenter plusieurs interfaces pour acquérir différentes capacités. Vous allez créer des appareils qui peuvent être à la fois contrôlables et dotés de fonctionnalités de gestion de l'alimentation.
Vous organiserez votre code sur quatre fichiers :
IControllable.cs: Définissez une interface nomméeIControllabledans l'espace de nomsSmartHome. Cette interface représente les appareils qui peuvent être allumés et éteints. Elle doit déclarer deux méthodes :TurnOn()etTurnOff(), retournant toutes deux une chaîne de caractères (string).INetworkConnected.cs: Définissez une interface nomméeINetworkConnecteddans l'espace de nomsSmartHome. Cette interface représente les appareils qui peuvent se connecter à un réseau. Elle doit déclarer une méthodeConnect(string network)qui retourne une chaîne de caractères (string).SmartTV.cs: Définissez une classeSmartTVdans l'espace de nomsSmartHomequi implémente à la foisIControllableetINetworkConnected. Le téléviseur doit avoir une propriétéBrand(string) et une propriétéScreenSize(int, représentant les pouces). Créez un constructeur qui accepte ces deux valeurs. Implémentez toutes les méthodes de l'interface :TurnOn()retourne"{Brand} {ScreenSize}-inch TV is now ON"TurnOff()retourne"{Brand} {ScreenSize}-inch TV is now OFF"Connect(string network)retourne"{Brand} TV connected to {network}"
Program.cs: Dans votre fichier principal, créez uneSmartTVen utilisant les valeurs d'entrée. Démontrez la flexibilité des interfaces multiples en stockant le même objet TV dans trois types de variables différents : le type concretSmartTV, une variableIControllableet une variableINetworkConnected. Appelez les méthodes appropriées via chaque référence pour montrer comment le même objet peut être traité différemment selon l'interface avec laquelle vous travaillez.
Vous recevrez trois entrées :
- Le nom de la marque du téléviseur
- La taille de l'écran en pouces
- Le nom du réseau auquel se connecter
Affichez la sortie dans ce format :
Via SmartTV:
{TurnOn() result}
{Connect(network) result}
Via IControllable:
{TurnOff() result}
Via INetworkConnected:
{Connect(network) result}Par exemple, si les entrées sont Samsung, 55, et HomeWiFi, la sortie devrait être :
Via SmartTV:
Samsung 55-inch TV is now ON
Samsung TV connected to HomeWiFi
Via IControllable:
Samsung 55-inch TV is now OFF
Via INetworkConnected:
Samsung TV connected to HomeWiFiRemarquez comment le même objet SmartTV peut être accédé via différentes références d'interface. Lorsqu'il est stocké en tant que IControllable, vous ne pouvez appeler que les méthodes de contrôle. Lorsqu'il est stocké en tant que INetworkConnected, vous ne pouvez appeler que les méthodes réseau. C'est toute la puissance de l'implémentation d'interfaces multiples : une classe acquiert plusieurs capacités tout en restant flexible dans la manière dont elle est utilisée !
Aide-mémoire
Une classe peut implémenter plusieurs interfaces en les énumérant après les deux-points, séparées par des virgules :
public interface IFlyable
{
void Fly();
}
public interface ISwimmable
{
void Swim();
}
public class Duck : IFlyable, ISwimmable
{
public void Fly()
{
Console.WriteLine("Flying through the air");
}
public void Swim()
{
Console.WriteLine("Swimming in the pond");
}
}La classe doit implémenter tous les membres de toutes les interfaces.
Lors de la combinaison de l'héritage avec plusieurs interfaces, la classe de base doit figurer en premier :
public class Duck : Bird, IFlyable, ISwimmable
{
// Hérite de Bird, implémente les deux interfaces
}Cela permet de composer des comportements à partir de plusieurs sources, chaque interface représentant une capacité unique.
Essayez vous-même
using System;
using SmartHome;
class Program
{
public static void Main(string[] args)
{
// Lire les entrées
string brand = Console.ReadLine();
int screenSize = Convert.ToInt32(Console.ReadLine());
string network = Console.ReadLine();
// TODO: Créer un objet SmartTV avec les valeurs d'entrée
// TODO: Stocker le même objet TV dans trois types de variables différents :
// 1. Type SmartTV (classe concrète)
// 2. Type IControllable (référence d'interface)
// 3. Type INetworkConnected (référence d'interface)
// TODO: Afficher la sortie au format requis :
// Via SmartTV :
// - Appeler TurnOn() et Connect(network)
// Via IControllable :
// - Appeler TurnOff()
// Via INetworkConnected :
// - Appeler Connect(network)
}
}
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
1Fondamentaux de la POO
Fichiers externesEspaces de noms et directivesIntro aux classes et objetsLe mot-clé 'this'Méthodes et paramètresChamps vs PropriétésConstructeursInitialiseurs d'objetsRécapitulatif - Calculatrice simple4Héritage
Syntaxe de base de l'héritage (:)Le mot-clé 'base'Mots-clés Virtual & OverrideClasses scelléesLa classe de base 'object'Récapitulatif - Hiérarchie des employés7Fonctionnalités avancées
Surcharge d'opérateursIndexeurs (this[])Redéfinition de ToString()Méthodes d'extensionRécapitulatif - Liste personnalisée10Patrons de conception - Partie 1
Introduction aux patrons de conceptionSingleton Thread-SafePatron FabriquePatron Observateur (Événements)Patron Stratégie2Propriétés et membres statiques
Propriétés auto-implémentéesPropriétés en lecture/écriture seuleChamps et méthodes statiquesClasses statiquesMembres à corps d'expression5Polymorphisme & Interfaces
Polymorphisme : Compilation vs ExécutionInterface vs Classe AbstraiteInterfaces MultiplesInterfaces ExplicitesUpcasting & DowncastingRécapitulatif - Calculateur de Formes8Concepts avancés de la POO
Composition plutôt qu'héritageGénériques (Classes et Méthodes)Délégués et ÉvénementsAttributs et RéflexionIDisposable et l'instruction usingBases de l'Injection de Dépendances11Patrons de conception, Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode TemplatePatron ÉtatPatron Composite3Architecture des classes
Données d'instance vs statiquesMots-clés 'readonly' & 'const'Champs de supportRécapitulatif - Gestionnaire de compte bancaire6Encapsulation
Modificateurs d'accèsPropriétés pour l'encapsulationImplémentation du masquage de donnéesPatterns d'immuabilitéRécapitulatif - Dossiers d'étudiants12Projet : Système de gestion de bibliothèque
Structure du projetModèles Livre et Utilisateur