“O singura interfata, mai multe metode” – sintagma pe care se bazeaza conceptul de polimorfism. Se incearca stabilirea unei interfete generice pentru un intreg grup de activitati asemanatoare.
Un obiect polimorfic este capabil sa ia mai multe forme, sa se afle in diferite stari, sa aiba comportamente diferite.
Polimorfismul parametric
O metoda va prelua orice numar de parametri.
Cand cream o metoda, de regula se stie numarul parametrilor care vor fi transmisi. Sunt cazuri in care nu se intampla acest lucru si va fi nevoie de un numar arbitrar de parametri. Se va recurge la un tip special de parametru, de tipul params. Acesta va declara un tablou de parametri, care poate memora zero sau mai multe elemente.
Exemplu :
//metoda va returna numarul minim public int metoda(params int[] numere) { int minim; //in cazul in care nu e transmis functiei //nici un parametru, afiseaza un mesaj if (numere.Length == 0) { Console.WriteLine("Nu sunt parametri"); return 0; } //initializam variabila //cu primul element al tabloului minim = numere[0]; //comparam fiecare element al tabloului //cu valoarea minima initiala foreach (int i in numere) if (i < minim) //atribuim valoarea minima variabilei minim minim = i; //inapoi la programul apelant al functiei return minim; }
Polimorfismul ad-hoc
Se mai numeste si supraincarcarea metodelor, una dintre cele mai interesante facilitati oferite de limbaju C#. Cu ajutorul acesteia, se pot defini in cadrul unei clase mai multe metode, toate avand acelasi nume, dar cu tipul si numarul parametrilor diferit. La compilare, se va apela functia dupa numarul parametrilor folositi la apel.
Pentru a supraincarca o metoda, pur si simplu trebuie doar declararea unor versiuni diferite ale sale. Nu este suficient insa, ca diferenta dintre doua metode sa fie facuta doar prin tipul valorii returnate, ci e nevoie si de tipurile sau numarul parametrilor.
Exemplu:
class SupraincarcareMetoda { public void CalculeazaMedia() { Console.WriteLine("Nici un parametru"); } //supraincarcam cu un parametru intreg public void CalculeazaMedia(int nota) { Console.WriteLine("O nota:" + nota); } //supraincarcam cu doi parametri intregi public void CalculeazaMedia(int nota1, int nota2) { Console.WriteLine("Doi parametri: " + nota1 + " " + nota2); } //supraincarcam cu parametri double public void CalculeazaMedia(double nota) { Console.WriteLine("Un parametru double:" + nota); } //eroare, daca incerc sa suprascriu //doar prin tipul de date returnat public int CalculeazaMedia(double nota) { // } }
In metoda principala a programului :
//apelam toate versiunile lui CalculeazaMedia SupraincarcareMetoda sup = new SupraincarcareMetoda(); sup.CalculeazaMedia(); sup.CalculeazaMedia(10); sup.CalculeazaMedia(23, 23); sup.CalculeazaMedia(34.34);
Polimorfismul de mostenire
Intr-o ierarhie de clase, se pune problema apelarii metodelor care au aceeasi lista de parametri, dar care sunt in clase diferite.
Exemplu:
class Baza { public void Afiseaza() { Console.WriteLine("Apelul functiei Afiseaza din clasa de baza\n"); } } class Derivata : Baza { public void Afiseaza() { Console.WriteLine("Apelul functiei Afiseaza din clasa derivata"); } }
La compilare se rezolva problema apelarii metode Afiseaza, pe baza tipului declarat al obiectelor :
Derivata obiect2 = new Derivata(); //instantiem pe un obiect din clasa derivata Baza obiect1 = obiect2; //afiseaza functia din clasa de Baza obiect1.Afiseaza(); obiect2.Afiseaza();
Modificatorii virtual si override
Virtual este folosit in declararea unei metode sau a unei proprietati. Acestea se vor numi membri virtuali. Implementarea unui membru virtual poate fi schimbata prin suprascrierea membrului intr-o clasa derivata.
Override se foloseste pentru a modifica o metoda sau o proprietate si furnizeaza o noua implementare a unui membru mostenit dintr-o clasa de baza. Metoda de baza suprascrisa si metoda de suprascriere trebuie sa aiba aceeasi signatura ( tip si numar de parametri ).
Implicit, metodele nu sunt virtuale. Nu se pot suprascrie metodele care nu sunt virtuale.
Exemplu:
class Baza { public virtual void Afiseaza() { Console.WriteLine("Apelul functiei Afiseaza din clasa de baza\n"); } } class Derivata : Baza { public override void Afiseaza() { Console.WriteLine("Apelul functiei Afiseaza din clasa derivata"); } }
Derivata obiect2 = new Derivata(); //instantiem pe un obiect din clasa derivata Baza obiect1 = obiect2; //afiseaza functia din clasa de Baza obiect1.Afiseaza(); obiect2.Afiseaza();
Polimorfismul ajuta la reducerea complexitatii pentru ca permite unei interfete sa fie folosita de fiecare data pentru specificarea unei clase generice de actiuni. Programatorul nu va efectua manual selectia. Selectia actiunii specifice (metoda) va fi facuta de compilator.