Newsgroup: it.comp.lang.visual-basic
Titolo: Polimorfismo in VB

Ho scritto questo msg in risposta ad un post precedente. Siccome mi sembra
che sia venuto benino (c'ho messo anche un pò a scriverlo!) lo estendo in
root per una migliore visibilità sperando possa essere utile a qualcuno:)
-----------------------------------------------------------
Una delle maggiori caratteristiche della tecnologia COM, che VB
supporta in pieno e che raramente viene usato è quello che in C viene
definito come polimorfinsmo, ovvero la possibilità di definire una funzione
che ha come parametro una variabile di tipo Object di cui la stessa non ne
conosce a priori le caratteristiche.
Es:
A.DLL fornisce una classe CLSA1 e CLSA2
B.DLL fornisce una classe CLSB1 e CLSB2
Tutti e 4 gli oggetti delle 2 dll hanno una proprietà ID Long e svariate
altre caratteristiche diverse per ciascuna classe. L'ID identifica, in ogni
classe la natura dell'oggetto
Nel progetto VB è possibile definire una funzione
Sub ProcessObj (UnknowObj as Object)
' elabora ua delle 4 classi contenute in 2 dll esterne.
' nb: tale classe potrebbe essere definita nel progetto stesso, in un OCX,
'in una DLL o in un'altro EXE
  On Error Resume Next
      Dummy&=UnknowObj.ID
  if Err<>0  Then Exit Sub          ' L'oggetto non ha una proprietà ID e
non può essere elabrato
  On Error Goto 0
     Select Case UnknowObj.ID
         Case 1
             ' la classe passata è di tipo 1
         Case 2
             ' la classe passata è di tipo 2
         Case 3
             ' la classe passata è di tipo 3
         Case 4
             ' la classe passata è di tipo 4
      End Select
End Sub
PrecessObj non conosce la natura dell'oggetto ma accetta qualsiasi classe, e
da al programmatore il compito di valutarla.
In C++ il polimorfismo è esteso a qualsiasi tipo di dati, variabili, array,
classi ecc.. In VB è consentito solo per le classi (non si può fare ad
esempio con tipi di dati definiti dall'utente) ma è ovvio che progettando
architetture del genere si possono fare cose notevoli veramente con poche
righe di codice.
I vantaggi nell'uso di questa tecnologia sono evidenti:
avendo una classe FORNO e svariate classi che descrivono cibi es: SALE,
FARINA, ACQUA, LIEVITO è possibile fare
Set PANE=FORNO.Cuoci(SALE.Join(FARINA.Join(ACQUA.Join(LIEVITO))))
l'esempio può sembrare stupido, ma se si osserva bene ci sono tutti gli
ingredienti per capirne i vantaggi :-)
--
Fabio Guerrazzi
http://www.sourcecode4free.com/cgt
fab...@libero.it
fab...@si.tdnet.it

 ha scritto
| -----------------------------------------------------------
| Una delle maggiori caratteristiche della tecnologia COM, che VB
| supporta in pieno e che raramente viene usato è quello che in C viene
| definito come polimorfinsmo,
Il C non conosce il polimorfismo. Questo e' una caratteristica dei linguaggi OO come ad esempio il
C++... :)))
| ovvero la possibilità di definire una funzione
| che ha come parametro una variabile di tipo Object di cui la stessa non ne
| conosce a priori le caratteristiche.
Ehm... il C posso usare i puntatori a "void" ed ottenere lo stesso risultato (con qualche magagna in
più nel maneggiare i puntatori, ma se uno sta attento non si scotta le mani). E quello che *non*
posso fare in C come *nemmeno* in VB e' poter scrivere due funzioni:
Function Somma(a As Integer, b As Integer) As Integer
    Somma = a + b
End Function
Function Somma(a As String, b As String) As Long
    Somma = a & b
End Function
Se il polimorfismo fosse supportato (pare che 
VB.NET
 lo farà) sarei in grado di compilare
correttamente un codice che comprenda le precedenti righe di codice...

"Jabba The Hutt" <Jabba....@Alderaan.SW> ha scritto
| Function Somma(a As String, b As String) As String
Ops... l'avevo pensata per i Long, ma poi ho cambiato in String i parametri per rendere ancora +
evidente la differenza nei paramentri... e mi sono scordato il tipo di dato restituito. :)))

correttamente un codice che comprenda le precedenti righe di codice...
Questo, piu' che polimorfismo, mi sembra overload ;-)
-- 
ciao, hal

 ha scritto
| >Function Somma(a As Integer, b As Integer) As Integer
| >    Somma = a + b
| >End Function
| >
| >Function Somma(a As String, b As String) As Long
| >    Somma = a & b
| >End Function
| >
| >Se il polimorfismo fosse supportato (pare che 
VB.NET
 lo farà) sarei in grado di compilare
| >correttamente un codice che comprenda le precedenti righe di codice...
|
| Questo, piu' che polimorfismo, mi sembra overload ;-)
Ehm, no: e' proprio polimorfismo...
L'overload e' un'altra cosa :-))))
Non lasciarti trarre in inganno dalle funzioni che eseguono una banale somma... rimangono pur sempre
due funzioni, e quello che cambia sono i parametri in ingresso (e cioe' il polimorfismo).
La soluzione proposta da Fabio e' un modo per aggirare l'ostacolo... ma non e' comunque
polimorfismo.

L'overload e' un'altra cosa :-))))
L' overload e' definire la stessa funzione in modi diversi a seconda
del tipo e del numero di parametri (come l' esempio di codice
che hai riportato).
Il polimorfismo e' l' implementazione di interfacce diverse.
-- 
ciao, hal

 ingresso (e cioe' il polimorfismo).
No. La possibilità di scrivere più funzioni con lo stesso nome che
accettino differenti parametri in ingresso è l'overloading.
Il polimorfismo (in VB) è questo (tratto da un messaggio che avevo
già postato):
'classe animale
public sub Parla()
    'solo interfaccia
end sub
'classe gatto
implements Animale
private sub Animale_Parla()
    msgbox "Miao"
end sub
'classe cane
implements Animale
private sub Animale_Parla()
    msgbox "Bau Bau"
end sub
'in un form
private sub FaiParlareAnimale(byref pet as animale)
    pet.parla
end sub
Alla funzione FaiParlareAnimale puoi passare sia un oggetto di
classe Gatto che un oggetto di classe cane (grazie al polimorfismo).
Il compilatore non sa di che classe sia pet, il tipo di pet puo'
essere risolto solo a run-time, pero' verra' richiamato il metodo
giusto a seconda dell'oggetto che verra' passato alla funzione.
Ciao.
--
BSD is for UNIX-lovers -- linux is for Windows-haters.

[cuttone]
argh! di polimorfismo non ci ho capito mai nulla *_*.
per fortuna che ci siete voi a far chiarezza :-P
ciao, assa.
--
Sito Comune
http://www.it-lang-vb.net/

 ha scritto
| L' overload e' definire la stessa funzione in modi diversi a seconda
| del tipo e del numero di parametri (come l' esempio di codice
| che hai riportato).
|
| Il polimorfismo e' l' implementazione di interfacce diverse.
Eh si, ho fatto un attimino confusione... mmm sono un po' arrugginito... :)))

"H.P.L." <u...@vaila.ble> ha scritto
| No. La possibilità di scrivere più funzioni con lo stesso nome che
| accettino differenti parametri in ingresso è l'overloading.
| Il polimorfismo (in VB) è questo (tratto da un messaggio che avevo
| già postato):
[...]
| Alla funzione FaiParlareAnimale puoi passare sia un oggetto di
| classe Gatto che un oggetto di classe cane (grazie al polimorfismo).
Si, hai ragione! Avevo fatto confusione...
Ottimo esempio!

 end sub
Aggiungo un pezzo perché sia più comprensibile:
Sub Pippo()
    dim pet as animale
    if (qualcosa) then
        set pet = new gatto
    else
        set pet = cane
    end if
    FaiParlareAnimale pet
end sub
In questo caso il tipo passato alla funzione FaiParlareAnimale può
essere risolto solo a run-time (e non a compile-time).


che il C non lo supporta lo sapevo, ho padellato i plus, ma che non fosse
polimorfismo no :/
ergo, ho cannato! :(
chiedo pietà, starò una settimana in ginocchio sui ceci
però come si chiama si chiama l'articolino almeno è giusto, no? :)
Fabio
"Jabba The Hutt" <Jabba....@Alderaan.SW> ha scritto nel messaggio
news:37n08.10169$sW5.4...@news2.tin.it...


 ha scritto
| che il C non lo supporta lo sapevo, ho padellato i plus, ma che non fosse
| polimorfismo no :/
|
| ergo, ho cannato! :(
| chiedo pietą, starņ una settimana in ginocchio sui ceci
Ehm, mi sa che sui ceci mi ci metto io... e per un mesetto finche' non avro' ripassato tutto il
libro di Eckel su Java e la programmazione ad oggetti...

quindi quello che ho esposto io è polimorfismo, allora avevo detto giusto?

 avevo detto giusto?
No, quella che hai esposto tu si chiama programmazione generica,
cioè la possibilità di scrivere funzioni che operano su oggetti
(parametri) di tipo non specificato e/o sconosciuto (quello che in
C++ si fa con i template).
Nel polimorfismo il tipo non è conosciuto a compile-time, ma è
soggetto a forti restrizioni; ad una classe che si aspetta un
parametro di un certo tipo (solo ed esclusivamente una classe) è
possibile passare un oggetto di una classe che implementi (con
Implements) la classe che si aspetta la funzione in questione, non
di una classe qualunque.
Polimorfismo, come dice la parola stessa, è la capacità di un
oggetto di avere "più forme". Nel esempio che ho fatto, un oggetto
di tipo gatto è in grado di comportarsi come classe gatto, ma anche
come classe animale (ha più forme).


Com'č? Il gatto non č un'animale, ma puň avere piů forme e interfacce, e
parlare come un cane? Dov'č che si scarica sta roba?
--
Starla. SP.
Sito Brutto: 
http://digilander.iol.it/starlasp
Sito Comune: 
http://www.it-lang-vb.net

 end sub
Era più comprensibile prima. Perchè il gatto è nuovo e il cane no? ;-)
Comunque la vera comodità di Implements è che ti aggiunge direttamente
nell'ide della form/modulo, tutte le funzioni della classe che devi
implementare. In questo modo è molto comodo riempire i metodi standard che
vuoi implementare, senza doverti scrivere ogni volta il nome della sub
pubblica, col rischio di sbagliarla.
Non ho mai capito perchè gli esempi che vengono fatti per spiegare la
funzionalità di implements siano così squisitamente astratti. Io la uso per
implementare delle funzionalità standard nelle form.
Se, ad esempio, vuoi che tutte le form MDIChild della tua applicazione
abbiano i metodi di Stampa, Esporta e Ricalcola, ti crei una interfaccia che
contiene questi metodi e la implementi in ciascuna delle tue form. Puoi
anche avere in interfaccia un metodi MetodiSupportati, da richiamare che ti
ritorni un identificativo dei metodi che supporta ciascuna form; una form
potrebbe non permettere la stampa, e un'altra potrebbe non permettere
l'esportazione. Questo è utile per riaggiornare lo stato
abilitato/disabilitato di toolbar e menu quando il focus passa da una form
MdiChild all'altra.
Il degno compare della Implements è il WithEvents, che permette di ereditare
non i metodi  (come fa la clausola Implements), ma gli eventi.
Questo è molto comodo per creare delle classi che, pur non contenendo
oggetti, possano rispondere direttamente ad eventi generati da oggetti.
Ad esempio è possibile creare una classe che popoli una lista, e che
posizioni esattamente la lista in base a ciò che viene scritto su di una
TextBox dall'utente. Dichiarando WithEvents una textbox all'interno della
classe, e accettando come parametro il textbox in questione, si può far
gestire autonomamente alla classe i comportamenti da seguire in base alle
modifiche che avvengono nel TextBox, senza bisogno di scrivere ad ogni
programma del codice negli eventi di quest'ultimo.
La menata è che è necessario pianificare bene prima i metodi della classe da
implementare. Se decidi di modificare i parametri di una delle funzioni
della tua classe, questi non vengono automaticamente modificati in tutti i
posti dove la implementi. Microsoft dice che questo non avviene
automaticamente per assicurare la congruenza tra le interfacce, ma alla fine
tocca comunque fare un gran lavoro di search&replace per rimettere tutto a
posto.
Ovviamente tutto sto pistolotto non era per H.P.L. che ha ampiamente
dimostrato di essere un esperto, ma solo per rendere un po' più terra-terra
il discorso per l'eventuale neofita che arrivato a questo punto si fosse
accorto di soffrire di un prodigioso mal di testa. 8-)
Ciao
*Roby*

accorto di soffrire di un prodigioso mal di testa. 8-)
Idem per quanto riguarda le mie considerazioni, sia per te che per gli
altri che hanno partecipato al thread...
Ciao,
Moreno
-- 
sirri at morenosoft dot com
Moreno Sirri VB Site - 
http://www.msvbsite.net
---------------------------------------------------------------------------
Le risposte alle tue domande le trovi sul Sito Comune di questo NewsGroup:
 
http://www.it-lang-vb.net
---------------------------------------------------------------------------

 tue form.
Certamente. Il mio esempio (astratto) riguardava il polimorfismo
(ottenibile utilizzando Implements), non Implements in sé stessa.


 implementazione questo non sarà più necessario...).
Volevo precisare una cosa. Il modo giusto di riutilizzare questo
tipo di codice già scritto non è l'ereditarietà, bensì il
contenimento (salvo casi particolari).
Ovvero, secondo il caso in questione (chiaramente il tutto andrebbe
poi analizzato più a fondo), l'utilizzo di un terzo componente
sarebbe la cosa giusta anche in presenza di ereditarietà.
Cercherò di spiegarmi meglio, perché il concetto non è dei più
semplici (ed è IT perché riguarda -anche- 
VB.NET
):
non bisogna ereditare per riutilizzare il codice della classe base,
ma bisogna ereditare per essere utilizzati da parte del codice che
utilizza la classe base (tramite il polimorfismo).
Spero di essermi spiegato perché non è facile e sono a disposizione
per chiarimenti.
Ciao




mmm.... in effetti è un po' contorto...
Io intendevo la possibilità di mantenere la stessa implementazione per
due classi che espongono la stessa interfaccia: in questo caso è più
comodo sfruttare l'eredità d'implementazione, no?
Altrimenti, se ho capito bene, il contenimento è attuabile già con le
versioni attuali di VB, però implica l'istanziazione (!?) di un terzo
componente (ovvero la classe "base") da parte della classe che necessita
di utilizzare quel codice (anche se in questo contesto mi sfugge dove
sta il polimorfismo).
Forse mi è sfuggito qualcosa; in ogni caso mi interesserebbe
approfondire il discorso...
Thnx


 utilizza la classe base (tramite il polimorfismo).
Toglimi una curiosità: tu fai il divulgatore per conto della Microsoft?
Te lo chiedo perchè ne conosco bene uno, e anche con lui (quando parla di
argomenti tecnici) non capisco niente. ;-)
Ti manca solo l'uso selvaggio dei TLA (Three-Letter Acronym) e poi ti
assumono di sicuro. :-)
No, seriamente, potresti spiegare in modo che capisca anche io?
Ciao
*Roby*

 anche io?
Leggi la mia risposta a Moreno, spero di essermi spiegato meglio.
Ciao.


 polimorfismo
Infatti in questo caso il polimorfismo non c'entra nulla.
Riutilizzare il codice per contenimento:
class Dummy
    'codice che voglio riutilizzare
    public sub Pippo()
        ...
    end sub
end class
'lo riutilizzo così
class FooBar
    private foo as Dummy
    'riutilizzo il codice di Dummy attraverso foo
    foo.Pippo
end class
Vediamo quando utilizzare l'ereditarietà.
Il primo, il più importante (dal quale non si può sfuggire) motivo:
alcune classi della libreria fornita .NET sono astratte
(MustInherit) e vanno quindi necessariamente ereditate, oppure per
accedere a membri protected di una classe.
- -
Per esprimere, come detto sopra, una relazione fra classi:
La classe A è e si_comporta_come la classe B.
Bisogna quindi ereditare (salvo particolari eccezioni che potrebbero
esserci) per esprimere solo e soltanto una relazione di tipo IS-A
(è-un) che obbedisce al principio di sostituzione di Liskov (LSP):
<< If for each object o1 of type S there is an object o2 of type T
such that for all programs P defined in terms of T, the behavior of
P is unchanged when o1  is substituted for o2 then S is a subtype of
T.>>
Quindi (spero di essere più chiaro) ereditare per essere
riutilizzati significa questo:
data una classe A da questa deriviamo una classe B per fare in modo
che tutto il codice che utilizza la classe A possa utilizzare anche
la classe B.
Se la relazione IS-A è valida grazie al LSP sappiamo che non avremo
problemi di sorta.
Spero (ma dubito) di essermi chiarito un po' meglio.
Ciao.


 _non_ e' un linguaggio OO <g>).
La verità è che la OOP non è semplice, e neppure intuitiva.
Nel mondo reale non siamo abituati a generalizzare e derivare metodi simili
da classi diverse, come ben dimostra il buffo commento su cani e gatti di
StarlaSP.
Per quanto ti possa sembrare un discorso eretico, l''approccio alla
programmazione ideale dovrebbe essere semplice quanto quello che si usa per
il mondo reale.
Al momento non è ancora possibile avere contemporaneamente in un linguaggio
duttilità e semplicità, ma io trovo VB un buon compromesso. Perfettibile, ma
non da buttare.
Anche M$ dovrebbe tenerlo presente. Se cerchi di convincere i tuoi clienti a
passare a qualcosa di più complesso devi prima convincerli che valga la
pena, e in questo senso, secondo me, al momento M$ ha fallito.
Con gli attuali grossi problemi del mercato del lavoro su internet, il
suffisso "NET" rischia perfino di tornargli a boomerang, e il mercato non è
fatto solo di grandi aziende americane, ma anche di innumerevoli piccole
aziende italiane (e straniere), che devono solo risolvere il problema di
gestirsi la loro piccola contabilità e/o il magazzino, e che di internet non
sanno cosa farsene (oltre a non avere intenzione di cambiare PC per
installare un applicativo nuovo e esoso in termini ri richieste hardware).
Certo, per me se sul lungo periodo ha successo un prodotto molto complesso
da imparare è meglio. Diminuiranno i "programmatori della domenica" e potrò
chiedere più soldi per lavorare, ma davvero è questa la cosa migliore per
tutti?
Ciao
*Roby*

 writes:
RP> Per  quanto ti  possa sembrare  un discorso  eretico, l''approccio
RP> alla programmazione ideale  dovrebbe essere semplice quanto quello
RP> che si usa per il mondo reale.
Per  avere   questo  bisognerebbe  risolvere   _alcuni_  problemi  "AI
completi"  nonche' trovare  un linguaggio  umano non  equivocabile. Mi
pare che sia  stato Leibnitz a dire "Calclemus!",  ovvero a pensare ad
un  linguaggio univoco  col  quale i  filosofi  potessero dirimere  le
discussioni "calcolando" la proposizione finale. E se non ricordo male
Platone in uno  dei suoi scritti va in loop infinito  in quanto ha una
parola che con la stessa grafia (philon con l'omega e il circonflesso)
ha significato sia attivo che  passivo, per cui non puo` piu` dirimere
se il simile ama il simile o il diverso :) :) :) ...
RP> duttilità e semplicità, ma io trovo VB un buon compromesso.
Trovo VB apparentemente semplice.  E apparentemente duttile. Ho dovuto
affrontare e risolvere  in VB problemi che sarebbe  stato assai facile
risolvere con un linguaggio verametne OO.
RP> Certo, per me se sul lungo periodo ha successo un prodotto molto complesso
RP> da imparare è meglio. Diminuiranno i "programmatori della domenica" e potrò
RP> chiedere più soldi per lavorare, ma davvero è questa la cosa migliore per
RP> tutti?
Per il cliente senz'altro. Avra` un prodotto di qualita`. Non ciofeche.
-- 
Gian  | main(){printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
Uberto|                        David Korn, 1987 ioccc best one liner 
Lauri |-------------------------------------------------------------------
(aka saint) >>Vedere X-Nospam nell'header - See X-Nospam field in Header<<

 Per il cliente senz'altro. Avra` un prodotto di qualita`. Non ciofeche.
Il cliente che la (mini)applicazione se la scrive in casa non sarà affatto
contento.
Questa è la cosa che più apprezzo in VB. Chiunque si può mettere e cercare
di scrivere del codice che risolva il suo problema. Il risultato può essere
più o meno brutto, ma il problema lo risolve la maggior parte delle persone
che prendono in mano lo strumento anche senza essere dei guru. Lo stesso non
si può certo dire del C++ .
Certo, quando vedi applicazioni commerciali scritte male, ti si ribaltano le
viscere, ed è più facile vederne di scritte in VB che in C++, ma non è di
questo che sto parlando. Lo scopo dell'ambiente di sviluppo deve essere
quello di permetterti di risolvere i problemi, non di costringerti a
risolverli in maniera elegante.
Riprendo l'esempio del mio messaggio precedente in cui parlavo delle molte
piccole aziende che devono risolvere solo il problema della contabilità al
PC: pensi che siano disposte a spendere di più per avere un prodotto scritto
in maniera più elegante con un linguaggio più nuovo?
E' il mercato che fa il successo del prodotto.
Ciao
*Roby*


Su questo, non ci piove.

 piu' importante e curata!
...ho visto anche di peggio...
ciao
ugo

 Per tutti non credo, ma per molti forse...
Su questo non siamo d'accordo. Se penso ai miei inizi da autodidatta, senza
uno straccio di manuale, né i soldi per potermelo permettere, e senza
Internet che era ben al di là da venire, devo benedire l'esistenza di un
linguaggio semplice come il Basic.
La semplicità di utilizzo e la possibilità di potersi mettere a scrivere da
subito del (brutto) codice, sono elementi indispensabili per appassionare le
nuove leve. Altrimenti la programmazione torna ad essere una attività di
nicchia, come all'epoca dei mainframe e degli analisti in camice bianco.
Passare ad altro in un secondo momento è sempre possibile. Serve studiare
ovviamente, ma è possibile.
Però per scoprire se quella è la tua strada, devi prima fare degli
esperimenti e venirne gratificato con una certa frequenza.
Just my 2 cents, obviously.
Ciao
*Roby*