Scriam in articolul despre mostenire (inheritance) ca mostenirea unei clase foarte importanta in C#. Dar, un altfel de mostenire, cea a interfetelor, are o putere mult mai mare.
O interfata defineste un set de metode, proprietati, evenimente, indexatori care vor fi implementate de o clasa. Atentie, interfetele NU implementeaza, ele sunt abstracte si doar isi descriu membrii. Interfata precizeaza CE trebuie facut, dar NU si CUM trebuie facut.
Sintactic, interfetele sunt asematoare cu clasele abstract, cu mentiunea ca nici o metoda nu poate avea corp. Se foloseste cuvantul cheie interface.
interface nume {
tip nume-metoda (param);
tip nume-metoda(param);
}
tip – tipul de date returnat de metoda,
param – signatura metodei, lista de parametri – numarul si tipul lor.
Toti membri declarati in interfata, sunt public in mod implicit.
public interface Interfata { void Metoda1(); void Metoda2(); }
Dupa definirea interfetei, o clasa o va putea implementa folosind aceeasi sintaxa ca la mostenirea unei clase de baza, prin specificarea numelui interfetei dupa numele clasei, separate de “:”.
Exemplu : selectam in Visual Studio numele interfetei si la click dreapta vom implementa interfata :
Codul, avand continutul metodelor modificat :
//clasa A implementeaza interfata Interfata class A : Interfata { #region Interfata Members public void Metoda1() { Console.WriteLine("Metoda1"); } public void Metoda2() { Console.WriteLine("Metoda2"); } #endregion }
La crearea unei interfete, ca restrictii avem faptul ca nu putem defini un constructor, un destructor, constante. Mai mult, o interfata nu poate mosteni o clasa sau o structura.
O interfata poate fi implementata de un numar infinit de clase.
O clasa poate implementa un numar infinit de interfete. Cand o clasa implementeaza o interfata, va trebui sa implementeze toate metodele acesteia, care sunt de tip public. Specificatorii de acces nu sunt permisi. O clasa nu poate alege pentru implementare doar anumite metode.
Exemplu:
public interface I1 { void Metoda1(); void Metoda2(); } public interface I2 { void Metoda3(); void Metoda4(); }
class A : I1, I2 { #region I1 Members public void Metoda1() { throw new NotImplementedException(); } public void Metoda2() { throw new NotImplementedException(); } #endregion #region I2 Members public void Metoda3() { throw new NotImplementedException(); } public void Metoda4() { throw new NotImplementedException(); } #endregion }
In cazul in care o clasa implementeaza mai multe interfete, numele acestora vor fi separate prin “,”. Este intalnita situatia cand o clasa va mosteni o clasa de baza si va implementa una sau mai multe interfete – numele clasei de baza trebuie sa fie primul in lista separata prin virgule.
Mostenirea interfetelor
O interfata poate mosteni o alta interfata. Sintaxa este comuna cu cea folosita la mostenirea claselelor. Daca o clasa mostenteste o interfata care mosteneste o alta interfata, clasa va trebui sa contina implementari pentru toti membri definiti pe lantul de mostenire al interfetei.
Exemplu :
//interfata accesibila in tot programul public interface A { void Metoda1(); void Metoda2(); } //interfata B va include metoda1 si metoda2 plus metoda3 public interface B : A { void Metoda3(); }
//clasa Test va trebui sa implementeze toate mteodele din A si B class Test : B { #region B Members public void Metoda3() { Console.WriteLine("Metoda3"); } #endregion #region A Members public void Metoda1() { Console.WriteLine("Metoda1"); } public void Metoda2() { Console.WriteLine("Metoda2"); } #endregion }
Si in cadrul mostenirii interfetelor, poate aparea situatia cand un membru al interfetei derivate are aceeasi signatura cu membrul cu acelasi nume din interfata de baza. Situatia va genera un mesaj de atentionare si va fi rezolvata prin folosirea operatorului new, daca se doreste ca membrul din interfata de baza sa fie ascuns. (la fel ca la mostenirea claselor).
O implementare explicita inseamna specificarea numelui complet, prefixand numele membrului cu numele interfetei. O implementare explicita este necesara pentru eliminarea ambiguitatii in cazul a doua interfete cu metode care au acelasi nume si aceasi signatura. Un alt motiv pentru implementarea explicita ar fi ca metoda respectiva nu va fi vizibila pentru codul din afara clasei.
Exemplu :
Pastram interfetele definite mai sus. Acum, selectam in Visual Studio numele interfetei si la click dreapta vom implementa interfata in mod explicit
Doar la implementarea metodei2 vom aduce modificari, pentru a fi vizibila in afara clasei.
class Test : B { #region B Members void B.Metoda3() { Console.WriteLine("Metoda3.Implementare explicita"); } #endregion #region A Members void A.Metoda1() { Console.WriteLine("Metoda1.Implementare explicita"); } //am adaugat public si am sters implementarea explicita public void Metoda2() { Console.WriteLine("Metoda2"); } #endregion }
//metodele implementate explicit, nu vor fi vizibile Test t = new Test(); t.Metoda2();
In .Net, printre cele mai folosite interfete se numara IDisposable, (folosita pentru eliberarea spatiului de memorie), IComparable (folosita pentru sortare), IConvertible (pentru convertirea la tipuri de baza), etc.
O interfata este o constructie pur abstracta. Pentru un programator, nu doar in C#, lucrul cu interfetele trebuie stapanit foarte bine.
Pingback/Trackback
Interfete vs. clase abstracte | by zeltera
Adi says:
Interesant tutorialul. Am citit si altele, insa nu am reusit sa inteleg f bine cand anume chiar avem nevoie sa folosim o interfata. Cu alte cuvinte, exista situatii in care este nevoie (obligatoriu) de implementarea unei interfete?
zeltera says:
Interfetele sunt notiuni putin mai avansate de programare si au un rol foarte important in implementarea unor solutii putin mai complicate (design patterns). Dupa ce o sa scrii vre-o 2 ani cod o sa intelegi utilitatea lor. Atat timp cat nu intelegi la ce folosesc si nu simti nevoia de a le folosi, uita de ele!
O sa incerc in viitor sa scriu cateva articole despre interfete. Stai pe aproape.
Alex says:
Salut, respect enorm si felicitari pentru ceea ce faceti aici, pot sa spun ca dupa ce am citit teoria si nici n-am ajuns la practica cu cartea si am facut tutorialele de pe acest site am inteles perfect cum functioneaza , obiectele , clasele , mostenirea , polimorfismul etc. Ca sa fiu on topic in legatura cu aceasta sectiune, vad ca mai sus ati scris ca in mod normal ajungem sa intelegem utilitatea interfetelor dupa vreo 2 ani de scris de cod … acum polemica mea este urmatoarea: Daca le invat din prima n-ar fi mai usor pentru lizibitatea codului ? Am citit in carte teoria despre aceste interfete si observ ca sunt o practica foarte buna pentru a “descurca” mai bine codul intr-un program. De ce considerati ca n-ar fi mai bine sa le utilizam de la inceput, din cauza ca sunt mai greu de implementat in program, sau din cauza ca e sintaxa mai complexa ? … precizez ca inca n-am inteles practic cum functioneaza dar vreau sa stiu pentru ca eu as vrea sa-mi formez de la inceput un anumit tipar in programare care pe viitor, o data cu practica sa intre in reflex si sa-mi fie mai usor in crearea aplicatiilor
zeltera says:
Daca ai inteles despre ce e vorba si cum se folosesc, evident, poti sa le folosesti. Ideea e ca interfetele sunt concepte putin mai greu de inteles tocmai pentru ca sunt legate de tehnici mai avansate de programare (sabloane – patterns). In acelasi timp, nu te pierde in structuri complexe pentru programe simple. interfetele sunt facute sa te ajute sa simplifici codul, sa implementezi mostenire (multipla) etc. Daca nu ai nevoie de asa ceva in structura codului pe care il scrii, nu le folosi.