offline
- Fil
- Legendarni građanin
- Pridružio: 11 Jun 2009
- Poruke: 16586
|
- 11Ovo se svidja korisnicima: Peca, Srki94, dr_Bora, diarno, mcrule, E.L.I.T.E., vasa.93, klodovik, Mila_90, thebrainstorm, Abadziluk
Registruj se da bi pohvalio/la poruku!
Klase
Klasa je skup objekata koji imaju zajedničku strukturu i ponašanje. Predstavlja strukturu podataka koju treba posmatrati kao novi tip.
Objekat je instanca klase i definiše se kao entitet koji je sposoban da čuva svoja stanja i koji okolini stavlja na raspolagaje skup operacija preko kojih se tim stanjima pristupa.
Objekat karakteriše njegov:
--> IDENTITET - razlikovanje objekata među sobom,
--> PONAŠANJE - dato preko skupa metoda koje sadrži objekat
--> STANJE - varijable (promenljive) vezane za objekat
//podvucimo još jednom da se stanja odnose na varijable, a ponašanje na metode
Direktan pristup podacima je nepotreban i nepoželjan
-->podatke treba "začauriti" (enkapsulirati)!
Postoje dva bitna aspekta enkapsulacije:
1. objedinjavanje podataka i funkcija u jedinstven entitet (preko klasa) ,
2. kontrola mogućnosti pristupa članovima entiteta (preko modifikatora pristupa).
//o modifikatorima pristupa je bilo reči u prethodnom članku
Enkapsulacija omogućava kontrolu korišćenja objekta (objekat se može koristiti isključivo preko javnih metoda/svojstava).
Instanciranje klasa
--> vrši se pomoću opreatora NEW:
Amf argus = new Amf();
Konstruktor je specijalna metoda koja:
- ima isti naziv kao i naziv klase,
- nema nikakvu povratnu vrednost.
Operator new vrši alokaciju memorije za objekat klase Amf, a metoda (konstruktor) Amf() kreira objekat.
Primer:
using System;
namespace Metode
{
class Amf
{
public string imeAmf;
public int brojResenihSlucajeva;
public void DodajSlucajeve(int broj)
{
brojResenihSlucajeva+=broj;
}
public void PrikaziStanje()
{
Console.WriteLine("Broj resenih slucajeva AMF-a {0} je: {1} ", this.imeAmf,this.brojResenihSlucajeva);
}
public static void Main (string[] args)
{
Amf amf = new Amf();
amf.imeAmf="Goran9888";
amf.DodajSlucajeve(70);
amf.PrikaziStanje();
}
}
}
Šta je ključna reč this?
--> upotrebom ključne reči this, implicitno se pokazuje na tekući objekat/parametar
(kod statičkih metoda se ne prosleđuje ovaj dodatni parametar, jer se ne pozivaju pomoću objekata)
Nasleđivanje
Nasleđivanje predstavlja jedan od koncepata Objekto Orijentisanog Programiranja (OOP).
-->omogućava da se na osnovu postojeće klase izvede nova klasa.
Izvedena klasa nasleđuje sve članove bazne klase.
// bazna klasa je super klasa ili nadređena klasa.
// izvedena klasa je podklasa ili podređena klasa (klasa koja nasleđuje baznu klasu).
Treba razlikovati nasleđivanje klasa od nasleđivanja interfejsa. Klasa koja nasleđuje interfejs treba da implementira sve navedene metode interfejsa.
- Nasleđivanje klasa može biti DIREKTNO I INDEREKTNO.
Indirektno, svaka klasa nasleđuje klasu Object.
- Jednu baznu klasu može da nasledi više izvedenih klasa (broj izvedenih klasa je neograničen).
- U programskim jezicima, nasleđivanje može biti i jednostruko i višestruko
--> C# podržava samo jednostruko nasleđivanje !
Grupa klasa koje su povezane nasleđivanjem formiraju strukturu koja se naziva hijerarhija klasa.
Slika: hijerarhija klasa
––> klase na višim nivoima su opštije (koncept generalizacije), dok su one na nižim nivoima u hijerarhiji specifičnije (koncept specijalizacije).
––> Dubina hijerarhije predstavlja broj nivoa nasleđivanja
//preporučuje se da dubina nasleđivanja bude do 7 nivoa.
Sintaksa nasledjivanja:
class IzvedenaKlasa:BaznaKlasa
{
...
}
Izvedena klasa nasleđuje sve osim konstruktora i destruktora bazne klase.
Ukoliko nije eksplicitno navedena bazna klasa podrazumeva se klasa System.Object.
––> javni članovi bazne klase su implicitno i javni članovi izvedene klase.
Primer je dat u pseudokodu:
public class Forumas
{
public void PosaljiPoruku(string tekst){...}
...............
}
public class Moderator: Forumas
{
}
...
Moderator simke = new Moderator();
simke.PosaljiPoruku("I da, za nijansu manje pijemo"); //pristup nasleđenoj metodi
- Izvedenoj klasi se, naravno, mogu dodati novi članovi.
- Nasleđivanje ne podrazumeva da će izvedena klasa imati pristup svim članovima bazne klase.
––> privatni članovi bazne klase, iako nasleđeni, su dostupni isključivo članovima bazne klase
––> članovi bazne klase sa modifikatorom protected su jedino dostupni unutar bazne klase i direktno i indirektno izvedenim klasama.
PODSETIMO SE: ukoliko modifikator pristupa nije naveden podrazumeva se da su članovi klase označeni sa "private".
Preporuka:
––> sva polja klase treba da imaju modifikator pristupa private, a za svako polje treba navesti svojstvo sa modifikatorom pristupa protected.
Dostupnost izvedene klase je uslovljena dostupnošću bazne klase
––> ukoliko je bazna klasa privatna, izvedena klasa ne može biti javna!
Za poziv konstuktora bazne klase iz konstruktora izvedene klase se koristi ključna reč base.
public class BaznaKlasa
{
public BaznaKlasa() {...}
}
public class IzvedenaKlasa: BaznaKlasa
{
public IzvedenaKlasa(): base() { ... }
}
// prvo se izvršava konstruktor bazne klase.
Pošto pričamo o nasleđivanju, treba predstaviti i koncept polimorfizma.
––> polimorfizam predstavlja sposobnost promenljive da referencira objekte različitih tipova i da automatski poziva odgovarajuću metodu objekta koji referencira.
// Polimorfizam se zasniva na ideji da metoda koja je deklarisana u osnovnoj klasi može da se implementira na više različitih načina u različitim izvedenim klasama.
Polimorfizam se realizuje preko virtualnih metoda
- za deklaraciju virtuelnih metoda se koristi ključna reč virtual.
- virtualne metode se mogu reimplementirati u izvedenim klasama (kod njih se koristi ključna reč override).
public class Forumas
{
public virtual void PrikaziForume() {...}
}
public class Moderator : Forumas
{
public override void PrikaziForume() {...}
}
--
// jer moderator vidi dodatne (skrivene potforume) koje ne vidi običan forumaš.
Virtuelna i reimplementirana (overrajdovana ) metoda moraju biti identične, tj. moraju imati:
isti naziv,
isti modifikator pristupa,
isti tip rezultata,
iste tipove parametara.
- Mogu se sakriti i virtuelne i nevirtuelne metode.
// sakrivanje metoda utiče na polimorfizam.
Primer polimorfizma (pseuokod):
public class Forumas
{
public virtual void PrikaziForume() {...}
}
public class Moderator : Forumas
{
public override void PrikaziForume() {...}
}
Forumas bobby = new Moderator();
bobby.PrikaziForume();
REZULTAT --> poziva se reimplementirana metoda
(pozvaće se metoda klase čijeg je tipa promenljiva)
Ukoliko ne želimo da drugi programeri, nasleđjuju neku od klasa, koje smo napravili
--> to možemo učiniti pomoću ključne reči sealed , a takve klase se nazivaju zapečaćene klase.
Zapečaćena (sealed) klasa ne može da se koristi kao bazna klasa bilo koje druge klase.
Sintaksa:
public sealed class ZapecacenaKlasa
{
//...
}
Interfejsi
Interfejs predstavlja "ugovor" kojim se garantuje da će se klasa, koja je nasledila taj interfejs, ponašati na određeni način.
// Dakle, klasa garantuje da prodržava metode, svojstva (properties), događaje (events) i indeksere nekog interfejsa!
Sintaksno
--> interfejs je klasa koja sadrži samo apstraktne metode.
Kada klasa implementira interfejs ona mora da implementira sve njene metode !
Moguće je da jedna klasa implementira više interfejsa.
(podsetimo se, višestruko nasleđivanje klasa nije dozvoljeno u C#, ali jeste višestruko nasleđivanje interfejsa).
Ukoliko želimo da proverimo da li objekat implementira interfejs učinićemo to na jedan od sledeća dva načina:
A) preko IS operatora:
npr. (kocka is ITelo)
--> vraća true ako se kocka može kastovati u ITelo.
B) preko AS operatora:
npr. (ITelo telo = kocka as ITelo)
--> ovaj način kombinuje IS i operacije kastovanja tako što prvo testira da li je kastovanje moguće a zatim kompletira kastovanje ako je moguće. Ukoliko kastovanje nije moguće operator AS vraća povratnu vrednost null.
//dakle, u ovom slučaju se provera vrši na indirektan način!
Apstraktna klasa je klasa koja se može naslediti, ali se ne može instacirati.
Može posedovati apstraktne metode, koje nemaju svoju implementaciju, ali ih klase naslednice (ukoliko nisu apstraktne) moraju implementirati korišćenjem ključne reči “override”.
Takođe, apstraktna klasa može imati metode koje imaju implementaciju (za razliku od interfejsa), i koje u svom telu mogu koristiti apstraktne metode.
Sveobuhvatan primer:
using System;
namespace ApstraktneKlase
{
public interface IRacun
{
void IsplatiSaRacuna(double iznos);
void UplatiNaRacun(double iznos);
string VratiPodatkeORacunu();
double VratiStanje();
}
public abstract class AbstractRacun : ApstraktneKlase.IRacun
{
private double stanje;
private string brojRacuna;
public AbstractRacun(string brojRacuna):this(brojRacuna, 0) { }
public AbstractRacun(string brojRacuna, double pocetnoStanje)
{
this.brojRacuna = brojRacuna;
this.stanje = pocetnoStanje;
}
public double VratiStanje()
{
return stanje;
}
public void UplatiNaRacun(double iznos)
{
stanje += iznos - ProvizijaNaUplatu(iznos);
}
public void IsplatiSaRacuna(double iznos)
{
stanje -= iznos + ProvizijaNaIsplatu(iznos);
}
protected abstract double ProvizijaNaUplatu(double iznos);
protected abstract double ProvizijaNaIsplatu(double iznos);
public virtual string VratiPodatkeORacunu()
{
string podaci = "Racun broj: " + brojRacuna+"\nIznos na racunu: " + stanje;
return podaci;
}
public class TekuciRacun:AbstractRacun
{
public TekuciRacun(string brojRacuna) : base(brojRacuna) { }
public TekuciRacun(string brojRacuna, double pocetnoStanje) : base(brojRacuna, pocetnoStanje) { }
protected override double ProvizijaNaUplatu(double iznos)
{
return 0;
}
protected override double ProvizijaNaIsplatu(double iznos)
{
double obracunataProvizija = 100 + (iznos * 3 / 100);
return obracunataProvizija;
}
public override string VratiPodatkeORacunu()
{
return base.VratiPodatkeORacunu() + "\nTip racuna: TEKUCI";
}
}
public class DevizniRacun:AbstractRacun
{
public DevizniRacun(string brojRacuna) : base(brojRacuna) { }
public DevizniRacun(string brojRacuna, double pocetnoStanje) : base(brojRacuna, pocetnoStanje) { }
protected override double ProvizijaNaUplatu(double iznos)
{
double obracunataProvizija = 100 + (iznos * 5 / 100);
return obracunataProvizija;
}
protected override double ProvizijaNaIsplatu(double iznos)
{
double obracunataProvizija = 100 + (iznos * 5 / 100);
return obracunataProvizija;
}
public override string VratiPodatkeORacunu()
{
return base.VratiPodatkeORacunu() + "\nTipRacuna: DEVIZNI";
}
}
public static void Main (string[] args)
{
AbstractRacun[] racuni = new AbstractRacun[2];
racuni[0] = new TekuciRacun("422-422", 0);
racuni[1] = new DevizniRacun("917-017", 0);
for (int i = 0; i < 2; i++)
{
Console.WriteLine("Uplata na " + i + ". racun u iznosu od 1000");
racuni[i].UplatiNaRacun(1000);
Console.WriteLine("Podaci o racunu posle uplate: \n"+racuni[i].VratiPodatkeORacunu());
Console.WriteLine();
}
}
}
}
Izlaz:
Izbegavanje konflikta između imena klasa u programima se obezbeđuje preko imenskih prostora (namespace)
Imenski prostor obezbeđuje kontejner koji sadrži aplikacioni kod, na takav način da i kod i njegov sadržaj mogu biti jedinsveno identifikovani.
Takođe, promoviše se ponovna upotreba koda. Imenski prostori se koriste i za kategorizaciju objekata u .NET okruženju.
C# kod se sadrži u globalnom imenovanom prostoru, a to znači da se tom kodu može pristupiti iz nekog drugog koda koji je unutar globalnog imenovanog prostora, i to tako što se navede njegovo ime.
Kao što je već dosada viđeno u primerima, koristi se ključna reč namespace , kako bi se eksplicitno definisao imenski prostor.
Ukoliko imamo kod u jednom imenovanom prostoru, koji treba da koristimo u drugom imenovanom prostoru, mora se uključiti referenca na prvi imenovani prostor.
|