19.10: Razlika između klase i strukture - lekcija -
Sintaksa strukture je:
Struct ime_strukture
{
članovi_strukture;
};
Članovi strukture mogu imati pored promenjivih i metode pa čak i konstruktore.
Struktura
ne može da sadrži druge strukture ili klase.
Vi ne možete imati
konstruktor u strukturi koji ne uzima ni jedan parametar. On već postoji
i implicitno inicijalizuje na nulu sva polja u strukturi.
Vi ne morate da koristite ključnu reč new da instancirate članove strukture ali nije zabranjeno.
Razlike između klase i strukture
Podaci su članovi klase ili strukture.
Klasa je referentni tip. Kada se kreira objekat klase, promenljiva kojoj je dodeljena u sebi sadrži u stvari pokazivač na njoj dodeljen prostor u memoriji.
Struktura je vrednosni tip. Kada se kreira struktura, promenljiva kojoj je dodeljena sadrži stvarne podatke.
Često pitanje u OOP načinu programiranju jeste koja je zapravo razlika između strukture i klase.
Prvo ću krenuti sa strukturom, struktura u C# programskom jeziku je value type što znači da se njena alokacija se uvek nalazi na steku (stack).
Klasa za razliku od strukture svoju alokaciju ima na heap-u tj. u
dinamičkoj dijelu memorije, u potpuno drugom logičkom djelu memorije u
odnosu na stek.
U primeni, strukturu ćemo najčešće naći kada radimo sa manjim tipovima
podataka i manjim količinama podataka, glavni razlog ove "odluke" jeste
taj što ona uveliko utiče na performanse naše App (aplikacije). Ako se
vodimo predhodno naučenim pojmom čuvanja strukture na steku, imamo
pojavu da kada želimo poslati strukturu u neku od funkcija, mi zapravo
tada šaljemo čitavu strukturu i njen sadržaj. Iz ovog možemo zaključiti
da u runtime-u imamo proces kompletnog kopiranja objekta onoliko puta
koliko pozivamo funkcija koje kao parametar preuzimaju našu strukturu.
Računica i zaključak je jednostavan: u slučaju veće strukture imamo
mnogo veće vreme izvršavanja koje uglavnom ide na kopiranje svih
informacija iz strukture u njenu lokalnu kopiju.
Važno za napomenuti je: da je stek mnogo manja logička količina memorija u
odnosu na heap, i proces slanja strukture kroz funkcije duplo povećava
zauzeće memorije na steku. Još jedna bitna stvar je da u funkciji mi
radimo sa kopijom objekta koji je poslat pri pozivu funkcije i svaku
promenu koju želimo raditi moramo na adekvatan način uraditi i na
"glavnom" objektu.
Kada uzmemo u obzir čitav proces kopiranja shvatimo koliko je ovo
"skupo" za našu App... Ako ovaj isti primer primenimo na klase koje su reference type,
iz jednog mini testa koji ćemo uraditi u sledećim koracima...dolazimo
do zaključka da se klase uvek šalju po referenci tj. u funkciju koja
prima našu klasu mi šaljemo adresu našeg objekta u dinamičkoj memoriji i
samim tim mi nemamo potrebu za kopiranjem onoga što se nalazi u klasi, a
sa ugla performansi šaljemo mnogo manju informaciju (za razliku do
strukture i slanja čitavog objekta). Kada prosledimo adresu (referencu)
mi u funkciji direktno pristupamo toj memorijskoj lokaciji i radimo
potrebne izmene nad našim objektom.
Malo objašnjenje za predhodne pojmove u slučaju da nisu jasne stvari oko
adresa. Svaki vaš objekat koji je smešten u memoriji ima svoju
memorijsku adresu tj. lokaciju na kojoj se nalazi. Kada vi imate
informaciju tj. adresu na kojoj je vaš objekat vi imate "pravo" i
mogućnost da ga direktno editujete... mnogo će biti jasnije u sledećem
primeru:
Na slikama ispod vidite kako izgleda naša struktura pod imenom "TackaKoordinateStruktura", njeni atributi i konstruktor:

kao i kod na kojem je definisana naša klasa "TackaKoordinateKlasa", atributi i konstruktor:

Kao što i vidite skoro da su identične, jedina razlika na prvi pogled je
u ključnim rečima class i struct. Ali naravno velika je razlika u
pozadini, a to ćemo upravo dokazati na sledeći način:
Za potrebu ovoga mini testa koristit ćemo dve funkcije koje kao
parametar primaju strukturu i klasu, naravno jedna prima strukturu, a
druga klasu i izgledaju ovako:

A u main funkciji imamo sledeću situaciju:

Ako pokrenemo naš program možemo očekivati sledeći ispis na konzoli:

Sa druge strane ako posmatramo ponašanje naše klase, pri inicijalizaciji je dobila vrednosti (7, 12), te u funkciji PromjenaStanjaKlase(), kao što je i definisano dobija vrednosti (20, 7), posle završetka sledi ispis koji nam ispisuje one vrednosti koje je klasa dobila u funkciji. Objašnjenje ovoga je da se klase uvek šalju po referenci, a ne po vrednosti kao što to strukture rade. Funkcija PromjenaStanjaKlase() dobila je adresu naše klase i mogla je direktno da utiče na promenu njenih atributa tj. modifikovali smo originalni objekat.
Iz ovog mini testa i primera dokazali smo i zaključili da se strukture uvijek šalju po vrednosti, a klase po referenci i ovo nam ujedno i govori pravu razliku između strukture i klase u C# programskom jeziku.