Saturday, April 27, 2024 02:16

Cuprins >> Programarea Orientată Pe Obiecte > Metode Virtuale

Metode Virtuale

Metodele virtuale sunt metode care pot fi suprascrise în clasele copil (derivate). În mod implicit, în .NET, metodele nu sunt virtuale. Pentru a declara o metodă ca virtuală, trebuie să o declaram folosind cuvântul cheie virtual, ca atare:

În acest caz, orice clasă care moștenește de la clasa în care este declarat MetodaMea(), poate avea și ea o metodă numită MetodaMea(), cu aceeași semnătură, care va înlocui metoda din clasa părinte. Abilitatea de a suprascrie metodele virtuale este o cerință fundamentală a polimorfismului, despre care voi vorbi într-o lecție viitoare.

Metoda care suprascrie o metodă virtuală din clasa părinte trebuie să utilizeze cuvântului cheie override.

Așa se declară metoda virtuală:

Această clasă de bază conține metoda virtuală Vaneaza(), a cărei semnătură acceptă un singur parametru de tip object. Aceasta înseamnă că orice clasă moștenitoare care dorește să suprascrie această metodă, trebuie să declare o metodă cu același nume și aceeași semnătură, astfel:

Explicația e simplă: avem două clase, Pisica și Leu, ambele moștenind din clasa de bază Felidae. Ambele suprascriu metoda Vaneaza(), oferind propria lor implementare personalizată și imprimând mesaje personalizate la consolă. Luați în considerare următorul exemplu:

care produce următoarea ieșire:

Implementare customizata suprascrisa de metoda virtuala

În primele două instanțe, ne-am așteptat să vedem că implementările Pisica și Leu sunt tipărite pe consolă, deoarece am suprascris metoda virtuală din clasa părinte în clasele copil. Cu toate acestea, puteți observa că deși a treia instanță a fost declarată de tip Felidae, am instanțiat-o de tip Leu și, prin urmare, a fost apelată metoda suprascrisă, și nu cea de bază, virtuală; consola nu a tipărit „Felidae vaneaza gazele”, ci a afișat „Leul vaneaza gazele”. Din aceasta, putem concluziona că metodele virtuale, precum și metodele abstracte, despre care voi vorbi într-o lecție viitoare, pot fi rescrise, suprascrise. De fapt, metodele abstracte sunt doar metode virtuale, dar fără o implementare concretă. De asemenea, vom afla ulterior că toate metodele definite în interfețe sunt abstracte și, prin urmare, virtuale, chiar dacă acest aspect nu este definit în mod explicit.

Acum, întrebarea logică vine în minte: care este utilitatea unei metode în clasa de bază, dacă este suprascrisă în clasa copil? De ce trebuie să o declaram în primul rând? Ei bine, există două motive pentru asta. În primul rând, s-ar putea să dorim să apelăm metoda virtuală din clasa copil, fără a o suprascrie:

Acesta va fi rezultatul:

Apelarea unei metode virtuale din clasa de baza

Deoarece nu am suprascris metoda Vaneaza() din clasa Pisica, când am apelat-o din instanța de tip Pisica, am apelat de fapt metoda virtuală a clasei de bază.

Un al doilea motiv ar fi faptul că, atunci când suprapunem metode virtuale în clasele copil, putem încă să apelăm în mod explicit implementarea virtuală din clasa de bază a metodei:

Iată rezultatul:

Metoda suprascrisa apeland metoda virtuala din clasa de baza

Deoarece în implementarea suprascrisă a metodei Vaneaza() am apelat și base.Vaneaza(prada), i-am spus compilatorului să apeleze în mod explicit și implementarea virtuală a metodei, din clasa de bază, executând în același timp instrucțiunile din implementarea suprascrisă. Aceasta înseamnă că dacă dorim, putem adăuga suplimentar funcționalitatea implementării de bază la funcționalitatea implementării suprascrise, executând efectiv ambele implementări.

Aceasta este diferența principală între o metodă suprascrisă și o metodă normală. Prima ne permite să schimbăm/completăm/modificăm o parte din funcționalitățile moștenite. Un exemplu simplu este metoda virtuală ToString(), pe care orice obiect .NET o are. Deoarece este declarată virtuală, o putem suprascrie în orice implementare, oferind o funcționalitate personalizată. Pot demonstra acest lucru cu următorul exemplu simplu:

Ieșirea va fi aceasta:

Implementarea implicita a metodei virtuale ToString()ceea ce nu este  foarte descriptiv. În schimb, pot să înlocuiesc această implementare virtuală implicită cu una personalizată, oferind o ieșire mult mai ușor de citit și înțeles:

iar ieșirea ar arăta acum astfel:

Implementare suprascrisa a metodei virtuale ToString()

Trebuie să recunoașteți, acesta este un mod mult mai frumos de a afișa un obiect.

Un aspect final al metodelor virtuale: dacă nu dorim ca metodele noastre suprascrise să fie modificate în continuare de alte clase care ar continua să moștenească clasa noastră, sau dacă dorim să oprim clasa noastră copil să mai fie moștenite de alte clase, putem folosi cuvântul cheie sealed. În principiu, acest cuvânt cheie spune că „această clasă/proprietate/metodă NU poate fi moștenită”. În această lumină, nu are sens să marcăm o metodă virtuală ca sealed. Cuvântul cheie override spune compilatorului că metoda poate fi suprascrisă de obiecte copil, dar cuvântul cheie sealed spune că metoda nu poate fi moștenită de o clasă copil în primul rând. De fapt, atunci când este utilizat pentru metode sau proprietăți, cuvântul cheie sealed este permis numai pentru metode sau proprietăți decorate cu cuvântul cheie override. În acest caz, cuvântul cheie sealed înseamnă că metoda sau proprietatea suprascrisă nu poate fi moștenită/modificată în continuare de clase care moștenesc clasa în care este declarată metoda ce suprascrie:

În lecția următoare, voi discuta despre conceptul abstract al programării.

Tags: , , , , , , ,

Leave a Reply



Follow the white rabbit