98-361: Programarea orientată pe obiecte

Partea de programare orientată pe obiecte se referă la 4 lucruri:

  • Ideea de bază din spatele unei clase
  • Înțelegerea conceptului de moștenire
  • Înțelegerea conceptului de polymorphism
  • Înțelegerea conceptului de encapsulare

În trecut am zis că totul în C# este un obiect! Eh, clasele sunt cele mai întâlnite tipuri de date în C#.

Principiile programării orientate pe obiect

O clasă este ca o schiță. Un blueprint al obiectului pe care eu vreau să îl creez. Ca orice obiect din lumea reală și obiectele din programare au proprietăți și metode (lucruri pe care le poate face).

Să luăm exemplul unui câine. Câinele este un obiect și poate fi transpuns în programare în felul următor:

  • Are număr de picioare (int nrPicioare=4;)
  • Are rasă (string rasa=”bulldog”;)
  • Are culoare blănii (string furColor=’black”;)

Tahltan_bear_dog_sketch

Și are și metode (acțiuni pe care le poate face):

  • Poate să latre (void bark() {….} )
  • Poate să dea din coadă (void wagTail() {…} )
  • Poate să comunice (string Speak() {…} )

Acum, asupra câinelui pot să fac diferite acțiuni/event-uri: să îl mângâi, să îi dau o comandă, etc în urma acestor event-uri normal că pot să schimb proprietăți sau să invoc metode (îi vopsesc verde și el latră de bucurie).

Știu sunt exemple triviale și ușor funny, dar pariu că ați înțeles cum stă treaba cu teoria din spatele obiectelor.

În cod tot ce am zis până acum:

class dog
{const int nrPicioare = 4;
string rasa;
string furColor;

void bark()
{}

void wagTail()
{}

string Speak()
{return “Woof Woof Woff!!”;}}

Bun, acum că am creat clasa dog ar fi normal să creăm și constructori. Prin constructori înțeleg inițializarea unui obiect după schița clasei. Astfel că toate obiectele dog pe care le voi crea vor avea proprietățile și metodele de mai sus.

Constructorul îl creez în interiorul clasei:

dog(string _rasa, string _fur) {
rasa=_rasa;
furColor=_fur;
}

Nu este obligatoriu să pun _ (underscore) în fața proprietății, dar așa m-am obișnuit și mă ajută la a diferenția proprietățile obiectului de cele ale clasei.

Apelarea constructorului ar trebui să o pot face de oriunde (*). De exemplul din blocul main al aplicației. Instanțierea unui obiect se va face mereu sub forma:

dog Cookie = new dog(“bichon”, “alb”);

Adică: obiect – numele obiectului = new obiect (proprietăți dacă este cazul);

Și acum pot apela metode pe care Cookie le poate face:

Cookie.WagTail();
string s=Cookie.Speak(“ham ham”);
Console.WriteLine(s);

Moștenirea

Atenție, încep iar cu exemple dubioase. Moștenirea se referă fix la ce îi spune și numele! Adică la cum o altă clasă o să aibă proprietățile unei clase părinte.

oop

Clasa B moștenește toate proprietățile și metodele clasei A și pe lângă acestea mai adaugă câteva (numele stapanului și metoda WagTail).

Când vorbim de moștenire trebuie să știm ce este aceea o clasă abstractă. O clasă abstractă se referă la o clasă pe care nu o pot folosi, dar din care pot să deriv alte clase. De exemplu clasa animal. Nu pot să spun că am fost la piață și mi-am cumpărat un animal. Dar pot spune că am fost la piață și mi-am cumpărat un cățel, o pisică sau un cal. Toate acestea derivând din clasa animal.

oop2

*Encapsularea și accesul

Prin encapsulare înțeleg limitarea accesului asupra unei clase și a unui obiect.
Am trei keyword-uri pe care trebuie să le știu:

  1. Private: această proprietate sau metodă nu poate fi accesată din afara clasei și în consecință nu poate fi moștenită.
  2. Public: această proprietate sau metodă poate fi accesată din afara clasei și poate să fie moștenită.
  3. Protected: această proprietate sau metodă poate fi accesată doar de către clasele care moștenesc din clasa părinte.

class myClass{
private int unInteger;
public string unMesaj;
protected void oFunctie();
}

Dacă vreau ca utilizatorul să poată face totuși modificări unor proprietăți trebuie să am foarte mare control asupra ceea ce poate modifica și dacă poate modifica. Aici intervine get și set.

class myClass{
private int val
public int randomVal{
get{return val;}
set{val=value;}
}}

Poate fi scris și ca:

public int randomVal{get;set;}

Value este predeterminat, este valoarea alături de care vine randomVal.

myClass myC= new myClass();
myC.randomVal=5;
int i=myC.randomVal;

Este bine de știut că pot să folosesc și get și set separat, astfel încât proprietatea devine readonly/writeonly.
O să iau exemplul unui supermarket și a unui adaos comercial. Eu nu vreau ca posibilul client să vadă prețul de achiziție și nici adaosul comercial ci să vadă doar prețul final al produsului:

class produs{
public decimal Pret {
get {return pretCumparare * adaosComercial;}
}
}
private decimal pretCumparare;
private decimal adaosComercial;
}

Overloading / supraîncărcarea

Suprascreirea se referă la scrierea mai multor metode cu același nume pe care le diferențiez prin tipul și numărul de inputuri pe care le ea.

string SaySomething (string s, string x);
string SaySomething(string x);
string SaySomething(int y);
string SaySomething();

Atenție, dacă aș folosi și int SaySomething() mi-ar da eroare pentru că suprascrierea diferă doar prin input nu și prin output!

Overriding / suprascirerea

Să fac override la o metosă se referă la aducerea unor noi implementări sau adăugări asupra acelei metode față de cele pe care le avea deja în momentul când a fost moștenită.

Primul exemplu care îmi vine în minte este telefonul. Suntem cu toții de acord că telefonul sună. Doar că sună în mod diferit în funcție de linia pe care o apelez.

oop3

 

  • Virtual: spun compilatorului că această metodă poate fi suprascrisă de clasele derivate.
  • Override: în subclasă spun compilatorului că această metodă suprascrie metoda părinte.
  • Base: în subclasă, apelez metoda părintelui

class A{
public virtual void myMethod() {….}
}
class B:A{
public override void myMethod() {….}
Base.myMethod();
}




Leave a Comment

Blog

Recent posts