Spiegare i concetti relativi alla varianza generica non è semplicissimo, soprattutto con l’uso di termini come Covarianza e di Controvarianza, e presuppone una conoscenza abbastanza approfondita della programmazione orientata agli oggetti, ma ci proveremo con qualche esempio.
Covarianza e Controvarianza sono, appunto, due aspetti distinti e complementari della Varianza generica, nell’ambito dell’ereditarietà in una gerarchia di classi.
Iniziamo con la Covarianza: supponiamo di avere un oggetto di tipo Insalata e un oggetto di tipo Carota e di voler assegnare questi oggetti a un oggetto di tipo Verdura. Per la programmazione orientata agli oggetti questo dovrebbe essere possibile, visto che Insalata e Carota sono classi che derivano dalla classe Verdura. Tuttavia, fino alla versione 2008 di Visual Basic, questo non era possibile perché era necessario effettuare una conversione esplicita.
In Visual Basic 2010, otteniamo il risultato desiderato dalle classi derivate Insalata e Carota, ma nell’ambito di una collezione di oggetti di tipo astratto Verdura. Questo risultato lo possiamo ottenere solamente utilizzando un’interfaccia IEnumerable(Of Object), dove Object in questo caso viene sostituito dal tipo Verdura.
Vediamo un esempio più semplice con una lista di stringhe:
Code Snippet
- ' definisce una lista di stringhe
- Dim listaStringhe As New List(Of String) From
- {
- "Visual Studio ",
- "2010 ",
- "su ",
- "io ",
- "Programmo"
- }
- ' definisce un insieme generico di elementi
- Dim lstCovarianza As IEnumerable(Of Object) =
- listaStringhe
- ' inizializza un oggetto di tipo StringBuilder
- ' per il concatenamento dinamico delle stringhe
- Dim sb As New StringBuilder
- ' ciclo per leggere tutte le stringhe
- ' dall'insieme generico
- For Each lst In lstCovarianza
- ' accoda la prossima stringa letta
- sb.Append(lst)
- Next
- ' visualizza il risultato
- MessageBox.Show(sb.ToString)
Nella Controvarianza, il concetto è diametralmente opposto: da una classe derivata Insalata o Carota, ricaviamo il risultato desiderato sfruttando la classe astratta Verdura.
Come nella Covarianza dobbiamo necessariamente utilizzare un’interfaccia IEnumerable, nella Controvarianza utilizziamo i delegati.
Come esempio classico di Controvarianza possiamo citare un metodo per gestire due eventi distinti di un controllo visuale: per esempio gli eventi MouseClick, cioè il normale click con il tasto sinistro del mouse, e KeyUp che avviene al momento del rilascio di un tasto.
Normalmente, questi due eventi ricevono due oggetti diversi: il primo riceve un oggetto di tipo MouseEventArgs, mentre il secondo riceve un oggetto di tipo KeyEventArgs. Si porrebbe, quindi, il problema di gestire questi due diversi tipi di oggetto. Per fortuna, entrambi sono derivati da System.EventArgs ed ereditano quindi tutte le caratteristiche principali da quest’ultimo.
In Visual Basic 2008 possiamo scrivere qualcosa di simile a questo codice:
Code Snippet
- ' definisco un metodo comune
- ' per i due diversi eventi
- Private Sub GestoreComune(
- ByVal sender As Object,
- ByVal e As EventArgs)
- ' visualizza un messaggio
- MessageBox.Show("Click o tasto!")
- End Sub
-
- ' questo ? il normale metodo gestore
- ' dell'evento Load di un form
- Private Sub frmMain_Load(
- ByVal sender As System.Object,
- ByVal e As System.EventArgs) _
- Handles MyBase.Load
- AddHandler btnTest.MouseClick,
- AddressOf GestoreComune
- AddHandler btnTest.KeyUp,
- AddressOf GestoreComune
- End Sub
In Visual Basic 2010 possiamo anche scrivere nella seguente forma alternativa:
Code Snippet
- ' funziona solo in VB 2010:
- AddHandler btnMessaggi.KeyUp,
- Sub() MessageBox.Show("Evento KeyUp")
-
- AddHandler btnMessaggi.Click,
- Sub()
- Dim msg As String
- msg = "Evento Click"
- MessageBox.Show(msg)
- End Sub
In questo esempio ridefiniamo gli eventi KeyUp e Click, in modo tale che se si verifica il primo evento viene visualizzato "Evento KeyUp", mentre se si verifica il secondo viene visualizzato "Evento Click".
Provate l’esempio e vedrete che le situazioni che potrete incontrare sono diverse. Per esempio, se portate il focus sul pulsante btnMessaggi e premete la barra degli spazi, vedrete apparire in sequenza entrambi i messaggi: questo avviene perché la pressione della barra degli spazi equivale a un click del mouse e quindi scatena l’evento Click, ma scatena anche l’evento KeyUp al momento del sollevamento del tasto. Se fate click con il mouse, vedrete il messaggio "Evento Click", mentre se premete qualsiasi altro tasto diverso dalla barra, vedrete il messaggio "Evento KeyUp".