Composizione invece dell'ereditarietà
Fa parte della sezione Programmazione orientata agli oggetti del percorso C# di Coddy. Lezione 41 di 70.
L’ereditarietà crea uno stretto accoppiamento tra le classi. Quando una Car eredita da Vehicle, qualsiasi modifica a Vehicle può compromettere Car. La composizione offre un’alternativa più flessibile: invece di ereditare un comportamento, una classe contiene oggetti che forniscono quel comportamento.
Considera un personaggio di gioco che può muoversi e attaccare. Con l'ereditarietà, potresti creare una gerarchia complessa. Con la composizione, ti basta assegnare al personaggio i componenti di cui ha bisogno:
public class MovementBehavior
{
public void Move() => Console.WriteLine("Moving...");
}
public class AttackBehavior
{
public void Attack() => Console.WriteLine("Attacking!");
}
public class Character
{
private MovementBehavior movement = new MovementBehavior();
private AttackBehavior attack = new AttackBehavior();
public void Move() => movement.Move();
public void Attack() => attack.Attack();
}La differenza fondamentale è la relazione. L'ereditarietà rappresenta «è-un» (un Dog è un Animal), mentre la composizione rappresenta «ha-un» (un Character ha un comportamento di movimento). La composizione ti permette di sostituire i comportamenti durante l'esecuzione, combinare liberamente le capacità ed evitare il fragile problema della classe base.
Usa l'ereditarietà quando esiste una vera relazione gerarchica. Scegli la composizione quando hai bisogno di flessibilità, quando i comportamenti potrebbero essere condivisi tra classi non correlate o quando vuoi modificare il comportamento in modo dinamico.
Sfida
FacileCostruiamo un sistema di notifiche che dimostra la potenza della composizione rispetto all'ereditarietà. Invece di creare una complessa gerarchia di classi per le notifiche, comporrai un NotificationSender assegnandogli componenti di comportamento intercambiabili.
Organizzerai il codice in tre file:
Behaviors.cs: crea due classi di comportamento nello spazio dei nomiNotificationsche gestiscono diversi aspetti dell'invio delle notifiche:FormattingBehavior- ha un metodoFormat(string message)che restituisce il messaggio racchiuso tra[ALERT]all'inizio e[END]alla fineDeliveryBehavior- ha un metodoDeliver(string channel, string message)che restituisce una stringa nel formatoSending via {channel}: {message}
NotificationSender.cs: crea una classeNotificationSendernello spazio dei nomiNotificationsche usa la composizione per combinare i comportamenti. Il tuo mittente deve:- contenere istanze sia di
FormattingBehaviorsia diDeliveryBehaviorcome campi privati - avere una proprietà
Channel(string) che memorizza il nome del canale di consegna - avere un costruttore che accetta il nome del canale
- avere un metodo
Send(string message)che prima formatta il messaggio usando il comportamento di formattazione, poi lo invia usando il comportamento di consegna e restituisce il risultato finale
- contenere istanze sia di
Program.cs: nel file principale, crea unNotificationSendercon un canale preso dall'input, quindi invia un messaggio preso dall'input. Stampa il risultato per mostrare come funzionano insieme i comportamenti composti.
Riceverai due input:
- Il nome del canale di consegna (ad es.,
Email,SMS) - Il messaggio da inviare
Stampa il risultato della chiamata a Send() sul tuo mittente di notifiche.
Ad esempio, se gli input sono Email e Server is down, l'output dovrebbe essere:
Sending via Email: [ALERT] Server is down [END]Nota che NotificationSender non eredita nulla: semplicemente "ha" comportamenti di formattazione e di consegna. Questo approccio basato sulla composizione significa che potresti sostituire facilmente uno dei due comportamenti senza modificare la classe del mittente, oppure riutilizzare questi comportamenti in classi completamente diverse!
Provalo tu
using System;
using Notifications;
class Program
{
public static void Main(string[] args)
{
// Leggi l'input
string channel = Console.ReadLine();
string message = Console.ReadLine();
// TODO: Crea un NotificationSender con il canale
// TODO: Invia il messaggio e stampa il risultato
}
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniNamespace e direttiveIntroduzione a classi e oggettiLa parola chiave "this"Metodi e parametriCampi e proprietàCostruttoriInizializzatori di oggettiRiepilogo - Calcolatrice semplice4Ereditarietà
Sintassi di base dell'ereditarietà (:)La parola chiave 'base'Parole chiave virtual e overrideClassi sealedLa classe base 'object'Riepilogo - Gerarchia dei dipendenti7Funzionalità avanzate
Sovraccarico degli operatoriIndicizzatori (this[])Override di ToString()Metodi di estensioneRiepilogo - Lista personalizzata10Pattern di progettazione Parte 1
Introduzione ai pattern di progettazioneSingleton thread-safePattern FactoryPattern Observer (eventi)Pattern Strategy2Proprietà e membri statici
Proprietà implementate automaticamenteProprietà di sola lettura e di sola scritturaCampi e metodi staticiClassi staticheMembri con corpo di espressione5Polimorfismo e interfacce
Polimorfismo a compile time e runtimeInterfaccia o classe astrattaInterfacce multipleInterfacce espliciteUpcasting e downcastingRipasso: calcolatore di forme8Concetti avanzati di programmazione a oggetti
Composizione invece dell'ereditarietàTipi generici (classi e metodi)Delegati ed eventiAttributi e reflectionIDisposable e istruzione usingNozioni di base sull'iniezione delle dipendenze11Pattern di progettazione, parte 2
Pattern del ComandoPattern dell’AdattatorePattern del DecoratorePattern Template MethodPattern dello StatoPattern Composito3Architettura delle classi
Dati di istanza vs staticiParole chiave 'readonly' e 'const'Campi di supportoRiepilogo - Gestore di conti bancari6Incapsulamento
Modificatori di accessoProprietà per l'incapsulamentoImplementazione dell'occultamento dei datiModelli di immutabilitàRiepilogo - Registri degli studentiEsercitati da solo: Compilatore C# online