overloading differenze nei vari linguaggi di elisa trifirò e barbara tacchino
TRANSCRIPT
Overloading
Differenze nei vari linguaggi
diElisa Trifirò e Barbara
Tacchino
Argomenti trattati Overloading: un tipo di
Polimorfismo Overloading in Java Overloading in C++ Overloading in C# Conclusioni
Classificazione di Cardelli-Wegner
La classificazione più completa risale al 1985 ed è opera di Luca Cardelli e Peter Wegner:
Polimorfismo universale Sono quelle funzioni che possono
operare su più tipi purché vengano rispettate alcune proprietà.
Polimorfismo parametrico: programmazione generica.
Polimorfismo per inclusione: programmazione ad oggetti.
Polimorfismo parametrico Idea: utilizzare un tipo come
parametro in una funzione generica.
E’ il compilatore che genera di volta in volta l’implementazione corretta.
Esempio: template in C++
Polimorfismo per inclusione
Nell'approccio object-oriented si definisce la classe degli elementi su cui ha senso applicare una certa funzione.
Tutte le classi da essa derivate ne erediteranno le funzioni, con la possibilità di ridefinirle.
Polimorfismo ad-hoc Nel polimorfismo ad-hoc rientrano: Overloading Coercion
Coercion Coercion: quando un valore di
un tipo viene visto (e talvolta trasformato) come valore di un altro tipo.
Esempio: nel sommare un float e un double, avviene una promozione da float a double.
Overloading Il termine overloading (da to
overload) significa sovraccaricamento e overloading delle funzioni indica la possibilità di attribuire allo stesso nome di funzione più significati.
Esempio: int x = 7 * 5; double y = 3.1 * 7.4;
Overloading in Java In Java é ammesso l’overloading
nel senso che é possibile definire più versioni di un metodo o costruttore che differiscono per la lista degli argomenti.
Esempio
class MyComplex{double a;double b;double m (MyComplex p){return p.a;}double m(double h){return this.a+h;}}Nota: non possono differire per il tipo di
ritorno.
Esempio In Java non é ammesso l’overloading di
operatori.
class MyComplex{double a,b;public MyComplex add(MyComplex m){this.a+=m.a;this.b+=m.breturn new MyComplex(this.a,this.b);}}
Risoluzione dell’overloading in Java
La risoluzione dell’overloading é la scelta della versione da applicare ad ogni chiamata di metodo.
In Java é fatta staticamente ossia al momento della compilazione.
Algoritmo di risoluzione dell’overloading in Java L’algoritmo di risoluzione é il seguente:1. Si cercano tutte le versioni del metodo
che potrebbero essere applicate, cioè con il nome giusto e con i tipi (statici)
2. Se si trovano più versioni applicabili, si elimina via via ogni versione meno “specifica” di un’altra
3. Se alla fine si arriva ad una sola versione, è quella da applicare, altrimenti si ha un errore statico
Considerazioni sulla risoluzione
dell’overloading in Java La risoluzione dell’overloading in
Java corrisponde ad un preprocessing che sostituisce al nome del metodo un nome esteso con le opportune informazioni di tipo.
Un esempio erratopublic class B { public void unMetodo()
{ System.out.println(“Glup!”); } public int unMetodo()
{ System.out.println(“Glup!”); return 1; }
}Questa classe dà errore in compilazione
perché non vi possono essere due metodi con lo stesso nome e stessi parametri anche se con tipi di ritorno differenti.
Dynamic binding in Java A run-time viene considerato il tipo
dinamico del ricevitore della chiamata di metodo e da quello avviene la ricerca gerarchica del metodo da scegliere.
Non viene considerato il tipo dinamico dei parametri.
Si continua ad andare in alto nella gerarchia di classi finché non si arriva al primo applicabile esattamente al tipo dinamico.
Esempio class A { h(int i){return 0}; f(){return 1}; s(double d){return 2}; } class B extends A { f(){return 3}; h(int i){return 4}; s(int i){return 5};} class C extends A { f(){return 6}; }
A a1=new B();A a2=new C();B b=new B();A a=new A();
Esempio
a.s(3.0); //2a1.s(3.0); //2b.s(0); //5b.s(1.0); //2((A) a1).h(4); //4
Overloading in C++ In C++ è permesso:1. Due funzioni con lo stesso nome ma
parametri e tipi di ritorno differenti: int media(int * array, int size); double media(double a,double b);2. Due parametri passati per riferimento
che differiscono per il qualificatore const sono considerati differenti:
void f(int&); void f(const int&);
Esempio In C++ e’ permesso l’overloading di
operatori: class MyComplex{ double a,b; MyComplex operator +(const
MyComplex &obj) { MyComplex temp; temp.a=(*this).a+obj.a; temp.b=(*this).b+obj.b; return temp; } };
Implementazione dell’overloading in C++
Ad ogni funzione del programma il compilatore assegna un nome interno che dipende dal nome della funzione e dai suoi parametri.
Il meccanismo di risoluzione dipende dal compilatore.
Risoluzione dell’overloading
in C++ Si passa attraverso un processo di
corrispondenza tra gli argomenti della chiamata e i parametri della funzione.
Il compilatore confronta gli argomenti della chiamata con le varie definizioni e se possibile ne invoca una.
Algoritmo di risoluzione dell’overloading in C++
La risoluzione avviene in tre passi:1. Identificazione delle funzioni
candidate (funzioni che hanno lo stesso nome della funzione chiamata)
2. Scelta delle funzioni utilizzabili (funzioni i cui parametri corrispondono agli argomenti della chiamata per numero e tipo)
Algoritmo di risoluzione dell’overloading in C++ 2
3. Scelta della migliore funzione utilizzabile ( funzione per cui gli argomenti corrispondono come tipi statici ai parametri)
Overloading in C# Si possono dichiarare più
metodi con lo stesso nome ma parametri diversi.
E’ permesso l’overloading di operatori.
E’ permesso l’overloading con tipi di ritorno diverso.
Esempio class MyComplex { double a,b; public static operator + (MyComplex
a,MyComplex q) { MyComplex z=new
MyComplex((p.a+q.a),(p.b+q.b)); return z;}}
Overloading di operatori in C# Gli operatori unari che possono
essere overloaded in C# sono : + - ! ~ ++ -- true false Gli operatori binari che possono
essere overloaded sono :+ - * / % & | ^ << >> == != > < >= <=
Risoluzione dell’overloading in C# L’insieme delle funzioni
candidate è ridotto a quelle funzioni applicabili rispetto alla lista degli argomenti.
Se questo insieme è vuoto si ha un errore in compilazione.
Altrimenti è scelta la migliore possibile.
Risoluzione dell’Overloading in C#
L’algoritmo di risoluzione è simile a quello utilizzato dal linguaggio Java.
Esempioclass A{…}class B : A {…}class C : B {…}class D {
public static void m(A a){…} public static void m(B b){…} public static void m(A a, B b){…} public static void m(B b, A a){…} }
Esempio (continuo) A a=new A(); C c=new C(); D d=new D(); d.m(a);/* D.m(A a) => d.m(A);*/ d.m(c);/* D.m(A a), D.m(B b)=>d.m(B) D.m(c,c);/*D.m(A a,B b), D.m(B b, A a)Error
Risoluzione degli operatori in C#
Le implementazioni degli operatori definite dall’utente hanno la precedenza su quelli predefiniti.
Overloading a run-time A differenza di Java durante
l’esecuzione, viene ignorato il tipo dinamico dell’oggetto che ha invocato il metodo e viene quindi applicato quello scelto a compile-time.
Linguaggio
overloading consentito
C++costruttori, distruttori, funzioni, operatori (tutti compresi ',' , 'new', 'delete' e '->')conversioni implicite (cast)
Java
costruttori e funzioni
C#
costruttori, funzioni e operatori ad esclusione di: '.', =, &&, ||, ?, : new e tutti gli operatori di assegnazione composti come += *= perché vengono sempre eseguiti con l'espansione delle operazioni semplici (evitando i problemi in cui sia stato fatto l'overloading degli operatori semplici e non di quelli composti)conversioni implicite (cast)
Conclusioni L’overloading, se usato
correttamente, migliora la leggibilità del codice evitando nomi con ridondanza di informazioni.
Esempio Volendo definire una funzione che
calcoli la potenza di interi e un’atra per i float, potremmo chiamarle in due modi diversi (es.IPow e FPow).
Questo però nasconde la similarità della loro funzionalità.
Conclusioni E’ difficile da gestire per il
compilatore. Il dynamic binding causa un
rallentamento nell’esecuzione. Il dynamic binding a run-time
potrebbe dare errori non segnalati in compile-time.