Dopo aver ragionato un bel po' e cercato spunti in rete, forse ho capito qualcosa:
Ripensando alla storiella del cuoco, che mi ero inventato per spiegare a me stesso alcune cose, riprendo la storia del maestro Cuoco che lascia all'apprendista in eredità la capacità di cucinare la pasta con un solo condimento, quindi questi elabora una tecnica tutta sua per cucinare la pasta con due condimenti e, in C++ e im VB, dimentica come si cucina la pasta a un solo condimento.
In effetti questa dimenticanza non è tanto normale.
Abbiamo rimediato ridichiarando il metodo nella classe derivata oppure, meglio, usando un'altra "formula" (che devo rivedere).
Ecco: using Cuoco::Pasta;.
Ma se io ho una classe Cuoco, molto complessa, magari, in cui l'utente non ci possa mettere le mani all'interno del codice o non voglia altrimenti ci esce pazzo a causa della complessità della classe, e la prendo così in blocco, e la voglio usare per creare con essa una classe derivata Apprendista che sappia cucinare anche la pasta a due condimenti, forse potrei desiderare che non si verifichi quel dannato inconveniente senza stare a specificare using Cuoco:Pasta; o simili per ogni nome di metodo della classe base...
In VB ho la soluzione!
Rifacciamoci il codice del cuoco che insegna all'apprendista la pasta a un condimento e dell'apprendista che se ne dimentica quando impara a farla a due...
#include "iostream" using namespace std; class Cuoco{ public: void Pasta(char * condimento){ cout << "io cucino la pasta con " << condimento << endl; getchar(); } }; class Apprendista: public Cuoco{ public: void Pasta(char * condimento, char * condimento2){ cout << "io cucino la pasta con " << condimento << " e " << condimento2 << endl; getchar(); } }; void main(){ Cuoco * Mario = new Cuoco(); Apprendista * Antonio = new Apprendista(); Mario->Pasta("sugo"); Antonio->Pasta("aglio", "olio"); Antonio->Pasta("ragu"); }
1>------ Inizio compilazione: Progetto: test15, Configurazione: Debug Win32 ------ 1> foglio1.cpp 1>c:\users\antonello\documents\visual studio 2010\projects\test15\test15\foglio1.cpp(28): error C2660: 'Apprendista::Pasta': la funzione non accetta 1 argomenti ========== Compilazione: 0 completate, 1 non riuscite, 0 aggiornate, 0 ignorate ==========Ecco: come ci aspettavamo...
Rifacciamolo in VB.NET, invece...
Module Module1 Class Cuoco Public Sub Pasta(condimento As String) Console.WriteLine("Io cucino la pasta con " & condimento) Console.ReadLine() End Sub End Class Class Apprendista Inherits Cuoco Public Sub Pasta(condimento As String, condimento2 As String) Console.WriteLine("Io cucino la pasta con " & condimento & " e " & condimento2) Console.ReadLine() End Sub End Class Sub main() Dim Mario As New Cuoco Dim Antonio As New Apprendista Mario.Pasta("sugo") Antonio.Pasta("aglio", "olio") Antonio.Pasta("ragu") End Sub End Module
Avviso 1 sub 'Pasta' nasconde un membro che supporta l'overload dichiarato nella class base 'Cuoco'. Per eseguire l'overload del metodo di base, quest'ultimo deve essere dichiarato 'Overloads'. C:\Users\Antonello\AppData\Local\Temporary Projects\ConsoleApplication1\Module1.vb 12 20 ConsoleApplication1 Errore 2 Argomento non specificato per il parametro 'condimento2' di 'Public Sub Pasta(condimento As String, condimento2 As String)'. C:\Users\Antonello\AppData\Local\Temporary Projects\ConsoleApplication1\Module1.vb 24 9 ConsoleApplication1Oltre al warning circa la parola chiave Overloads ottengo il previsto messaggio di errore, sempre dovuto al fatto che, come in C++, l'apprendista si è scordato di come si fa la pasta a un condimento solo!
Ma se rispettiamo il warning e mettiamo Overloads, cosa succede?
Succede che l'apprendista non si scorda più di come si fa la pasta a un condimento!.
Module Module1 Class Cuoco Public Sub Pasta(condimento As String) Console.WriteLine("Io cucino la pasta con " & condimento) Console.ReadLine() End Sub End Class Class Apprendista Inherits Cuoco Public Overloads Sub Pasta(condimento As String, condimento2 As String) Console.WriteLine("Io cucino la pasta con " & condimento & " e " & condimento2) Console.ReadLine() End Sub End Class Sub main() Dim Mario As New Cuoco Dim Antonio As New Apprendista Mario.Pasta("sugo") Antonio.Pasta("aglio", "olio") Antonio.Pasta("ragu") End Sub End Module
Io cucino la pasta con sugo Io cucino la pasta con aglio e olio Io cucino la pasta con ragu
Bene.
Qui Overloads ha senso perché io ho specificato un metodo dalla firma diversa, per cui si va a dire al compilatore: guarda che questo metodo io non lo voglio sostituire agli altri con lo stesso nome, ma solo affiancare per fare l'overload, e così non mi nascondere gli altri metodi con lo stesso nome, come Pasta a un condimento che è stato ereditato.
Ma che senso ha mettere Overloads quando il metodo ha lo stesso nome e la stessa firma?
Module Module1 Class Cuoco Public Sub Pasta(condimento As String) Console.WriteLine("Io cucino la pasta con " & condimento) Console.ReadLine() End Sub End Class Class Apprendista Inherits Cuoco Public Sub Pasta(condimento As String) Console.WriteLine("Io cucino la pasta con " & condimento) Console.ReadLine() End Sub End Class Sub main() Dim Mario As New Cuoco Dim Antonio As New Apprendista Mario.Pasta("sugo") Antonio.Pasta("sugo") End Sub End ModuleMi sembra implicito che questo metodo nasconda quello ereditato... e se poi ne vogliamo mettere degli altri basta fare Overloads con questi...
Ma che senso ha mettere Overloads nel caso in cui io ho un solo metodo che nasconde e sostituisce un solo metodo con la firma uguale ereditato dalla classe base?
Perché in questo caso...
Module Module1 Class Cuoco Public Sub Pasta(condimento As String) Console.WriteLine("Io cucino la pasta con " & condimento) Console.ReadLine() End Sub End Class Class Apprendista Inherits Cuoco Public Sub Pasta(condimento As String) Console.WriteLine("Io cucino la pasta con " & condimento) Console.ReadLine() End Sub End Class Sub main() Dim Mario As New Cuoco Dim Antonio As New Apprendista Mario.Pasta("sugo") Antonio.Pasta("sugo") End Sub End Module...ottengo un warning per non aver messo Overloads nella ridichiarazione del metodo nella classe derivata, quando il risultato è lo stesso?
non conoscere la classe base! Che ne so, io, se nella classe base oltre al metodo che voglio nascondere ci siano altri metodi con lo stesso nome e firma diversa che mi vengono tutti nascosti se io non uso Overloads?
Vallo a trovare, poi, dove sta l'errore se io devo chiamare un metodo con lo stesso nome ereditato nella classe derivata, che è stato nascosto dal metodo che ho ridichiarato nella classe derivata con lo stesso nome!
Ecco, io non conosco la classe Cuoco, e non so che contiene anche un metodo Pasta() senza condimenti:
Module Module1 Class Cuoco Public Sub Pasta(condimento As String) Console.WriteLine("Io cucino la pasta con " & condimento) Console.ReadLine() End Sub Public Sub Pasta() Console.WriteLine("io cucino la pasta senza condimenti") Console.ReadLine() End Sub End Class Class Apprendista Inherits Cuoco Public Sub Pasta(condimento As String) Console.WriteLine("Io cucino la pasta con " & condimento) Console.ReadLine() End Sub End Class Sub main() Dim Mario As New Cuoco Dim Antonio As New Apprendista Mario.Pasta("sugo") Antonio.Pasta("sugo") Antonio.Pasta() End Sub End Modulee ridichiarando Pasta(condimento as string) nella classe Apprendista ho cancellato Pasta().
Poi, in questa classe, ma magari anche in una lontana discendente, voglio utilizzare questo metodo e non lo trovo! In questo caso qui sopra l'ho utilizzato in Apprendista, ma metti che io creo una classe Apprendista e la metto da parte, e magari dopo un anno io la riprendo e ci creo una classe Sottoapprendista, e poi dopo sei mesi un altro prende questa e ci crea una classe Sottoapprendistainfimo eccetera eccetera... e magari gli viene in mente che questo deve fare la pasta senza condimento: esso non ne sarà più in grado perché suo nonno Apprendista, non mettendo Overloads, aveva cancellato l'eredità Pasta() che gli aveva lasciato suo padre!
Nessun commento:
Posta un commento