Razlike između klase i strukture
Struktura se deklariše kao i enumeracija ili klasa, samo što koristi ključnu reč struct. Sintaksa strukture je:
Struct ime_strukture
{
članovi_strukture;
};
Članovi strukture mogu imati pored promenjivih i metode i čak konstruktore. Strukture jesu izvedene iz klase Object, ali one ne mogu da vrše nasleđivanje. To u prevodu znači da 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. Struktura ne može da sadrži destruktor. Vi ne morate da koristite ključnu reč new da instacirate članove strukture ali nije zabranjeno. To takođe ne znači da ćete sa ključnom rečju new prebaciti deo memorije strukture sa steka na hip. Struktura se isključivo formira u stek segmentu.
Razlike između klase i strukture
Podaci su članovi klase ili strukture.
Klasa je referentni tip. Kada se kreira objekat klase, promenljiva kojoj je dodeljen zauzima prostor u memoriji.
Struktura je vrednosni tip. Kada se kreira struktura, promenljiva kojoj je dodeljena sadrži stvarne podatke.
Ostale razlike:
-
Za razliku od klasa, u strukturi ne može da se deklariše podrazumevani konstruktor. Razlog tome je što ga kompajler uvek generiše. Dok kod klasa kompajler generiše podrazumevani konstruktor samo u slučaju kada ga programer nije deklarisao.
-
U klasi, može da se inicijalizuju instance polja kada se deklarišu, dok u strukturi to nije moguće.
Kao i kod klasa i kod struktura može da se deklariše konstruktor sa parametrima.
Primer strukture:
using System;
namespace App
{
public struct Tacka
{
private double x;
private double y;
public Tacka(double x, double y)
{
this.x = x;
this.y = y;
}
public double UdaljenostOdKorPoc()
{
return Math.Sqrt(Math.Pow(this.x, 2) + Math.Pow(this.y, 2));
}
}
class Program
{
static void Main(string[] args)
{
Tacka T1 = new Tacka(3, 6);
Console.WriteLine("Udaljenost T1 od koordinatnog pocetka: {0}", T1.UdaljenostOdKorPoc());
Tacka T2 = new Tacka();
Console.WriteLine("Udaljenost T2 od koordinatnog pocetka: {0}", T2.UdaljenostOdKorPoc());
}
}Primer klase:
using System;
namespace App
{
public class Tacka
{
private double x;
private double y;
public Tacka()
{
x = 0;
y = 0;
}
public Tacka(double x, double y)
{
this.x = x;
this.y = y;
}
public double UdaljenostOdKorPoc()
{
return Math.Sqrt(Math.Pow(this.x, 2) + Math.Pow(this.y, 2));
}
}
class Program
{
static void Main(string[] args)
{
Tacka T1 = new Tacka(3, 6);
Console.WriteLine("Udaljenost T1 od koordinatnog pocetka: {0}", T1.UdaljenostOdKorPoc());
}
}
}
****** Malo detaljnije objašnjenje - za one koji žele da znaju više:
Razlika između Struct i Class u C# programskom jeziku
Č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;


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

Ako pažljivo pratimo ispis na konzoli, možemo primetiti da se vrednost atributa naše strukture promeni samo u funkciji PromjenaStanjaStrukture(), kada se završila funkcija u mainu imamo informaciju da je vrednost atributa strukture ista kao i pre poziva. Iz ovoga možemo zaključiti samo jedno, da je naša struktura po svojoj prirodi poslata u funkciju po vrednosti i da smo u funkciji radili i vršili promene sa njenom kopijom koja je naravno uništena pri završetku funkcije (silazak sa steka).
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.