340 likes | 551 Views
Dostop do stanj objekta. Možnost, da neposredno dostopamo do stanj/lastnosti objekta NI NAJBOLJŠI ! Ne le, da ni najboljši, je == CENZURA == Nobene kontrole nad pravilnostjo podatkov o objektu! rjavko.masa = -3.2;
E N D
Dostop do stanj objekta Možnost, da neposredno dostopamo do stanj/lastnosti objekta NI NAJBOLJŠI! Ne le, da ni najboljši, je == CENZURA == Nobene kontrole nad pravilnostjo podatkov o objektu! rjavko.masa = -3.2; Ker ne moremo vedeti, ali so podatki pravilni -vsi postopki po nepotrebnem bolj zapleteni Objekt naj sam poskrbi, da bo v pravilnem stanju Težave, če moramo kasneje spremeniti način predstavitve podatkov o objektu
Zgled public class TestClan{ public static void Main(string[] args) { Clan novClan = new Clan(); novClan.ime = "Katarina"; novClan.letoVpisa= 208;
Dodajmo metodo Ni problem, napisali bomo metodo, ki bo vnos preverjala public class Clan { public string ime; public string priimek; public intletoVpisa; public string vpisnaStevilka; … // konstruktorji in metodekotprej! public boolSpremeniLetoVpisa(intleto) { if ((2000 <= leto) && (leto <= 2020)) { this.letoVpisa= leto; return true; //leto je smiselno, popravimostanjeobjekta in vrnemo true } return false; // letonismiselno, ne spremenimo nič in vrnemo false } }
Uporaba metode Neposredno spremenimo leto Leto se ne spremeni Leto se spremeni novClan.letoVpisa = 20008; Še vedno lahko napačno popravilo leto public class TestKlub { public static void Main(string[] args) { Clan novClan = new Clan(); novClan.ime = "Katarina"; novClan.letoVpisa= 2007; novClan.SpremeniLetoVpisa(208); novClan.SpremeniLetoVpisa(2008);
Dostopi do stanj ime_objekta.stanje Zakaj je to lahko problem? “zunanji” uporabnik nastavi napačno vrednost z1.masa = -100.10; Uporabnik pozna predstavitev Kasneje je ni mogoče spremeniti Načini dostopa public private protected internal public string serijska; private Datum datumRojstva; private double masa; public int[] tab; bool spol; Ostale pozabimo Izogibajmo!
public Znotraj razreda NI omejitev, vedno (ne glede na način dostopa) je možen dostop do komponent. public Do lastnosti lahko dostopajo vsi, od kjerkoli (iz katerihkoli datotek (razredov)) imeObjekta.lastnost public int javnaLastnost; // v razredu MojObjekt Kdorkoli naredi objekt vrste MojObjekt MojObjekt x = new MojObjekt(); lahko dostopa do javnaLastnost x.javnaLastnost
private private Do lastnosti ne more dostopati nihče, razen metod znotraj razreda Ko pišemo načrt razreda this.lastnost lastnost private int privatnaLastnost; // v razredu MojObjekt Če kdo naredi objekt vrste MojObjekt MojObjekt x = new MojObjekt(); Pri poskusu dostopa do privatnaLastnost x.privatnaLastnost Prevajalnik javi napako
Razred Zajec public class Zajec { public string serijska; // serijska stevilka zajca public bool spol; // true = moski, false = zenska privatedouble masa; // masa zajca ob zadnjem pregledu } public class Zajčnik { public static void Main(string[] ar) { Zajec z1 = new Zajec(); z1.serijska = "1238-12-0“; z1.spol = false; z1.masa = 0.12; z1.masa = z1.masa + 0.3; Console.WriteLine("Zajec ima ser. št.:" + z1.serijska); } } Prevajalnik javi NAPAKO!!
Razred Zajec2 public class Zajec2 { public string serijska; // serijska stevilka zajca public bool spol; // true = moski, false = zenska privatedouble masa; // masa zajca ob zadnjem pregledu public SpremeniTezo(double x) { this.masa = x; } } Ok pri prevajanju! Ok pri prevajanju! public class Zajčnik { public static void Main(string[] ar) { Zajec z1 = new Zajec2(); z1.serijska = "1238-12-0“; z1.spol = false; z1.SpremeniTezo(0.11); z1.masa = 0.12; z1.masa = z1.masa + 0.3; Console.WriteLine("Zajec ima ser. št.:" + z1.serijska); } } Prevajalnik javi NAPAKO!!
Dostop do stanj/lastnost Kako uporabiti: Metode za dostop do stanj "get" metode Metode za nastavljanje stanj "set" metode Zakaj je boljši dostop preko metod kot neposredno Možnost kontrole pravilnosti! Možnost kasnejše spremembe načina predstavitve (hranjenja podatkov)
Dostop do stanj/lastnost Zakaj je boljši dostop preko metod kot neposredno Možnost oblikovanja pogleda na podatke Podatke uporabniku posredujemo drugače, kot jih hranimo (datum – interno je mesec število (1, 2, ...), "navzven" kot ime ("januar", "februar" ...) Dostop do določenih lastnosti lahko omejimo Npr. spol lahko nastavimo le, ko naredimo objekt (kasneje ne, saj se ne spreminja... če odmislimo kakšne operacije, določene vrste živali ... seveda.) Hranimo lahko tudi določene podatke, ki jih uporabnik sploh ne potrebuje ..
Nastavitve stanj/podatkov Nastavitve stanj “prireditveni stavek” zajcek.SpremeniTezo(2.5); V bistvu isto kot zajcek.masa = 2.5; A metoda spremeniTezo lahko PREVERI, če je taka sprememba teže smiselna! zajcek.SpremeniTezo(-12.5); V bistvu isto kot zajcek.masa = -12.5; A tu bomo lahko PREPREČILI postavitev lastnosti objekta v napačno stanje!
Razred Zajec - SpremeniTezo public void SpremeniTezo(double novaTeza) { // smislena nova teza je le med 0 in 10 kgif ((0 < novaTeza) && (novaTeza <= 10)) this.masa = novaTeza; // v nasprotnem primeru NE spremenimo teže } public bool SpremeniTezo(double novaTeza) { // smislena nova teza je le med 0 in 10 kgif ((0 < novaTeza) && (novaTeza <= 10)){ this.masa = novaTeza; return true; // sprememba uspela } // v nasprotnem primeru NE spremenimo teže // in javimo, da spremembe nismo naredili return false; }
SpremeniTezo Imamo lahko OBE metodi? NE Imata enak podpis (ime + tipi parametrov) Tip rezultata NI del podpisa! Metoda je seveda lahko bolj kompleksna – denimo vemo, da se teža ne more spremeniti bolj kot za 15% public bool SpremeniTezo(double novaTeza) { // smislena nova teza je le med 0 in 10 kg // in če ni več kot 15% spremembe od zadnjič int sprememba = (int)(0.5 + (100 * Math.abs(this.masa – novaTeza) / this.masa); if ((0 < novaTeza) && (novaTeza <= 10) && (sprememba <= 15) ){ masa = novaTeza; // this.masa ... Lahko pa this spustimo! return true; // sprememba uspela } // v nasprotnem primeru NE spremenimo teže // in javimo, da spremembe nismo naredili return false; }
Teža in konstruktor Seveda je smiselno, da zagotovimo, da je teža ustrezna že ves čas! Pozor na začetno stanje: konstruktor! Tudi v konstruktorju preverimo, če se uporabnik "obnaša lepo" Pogosto na to pozabimo Zajec neki = new Zajec("X532", true, 105); 105 kilogramskega zajca verjetno ni, a uporabnik je pozabil na decimalno piko v 1.05 Zato je kontrola smiselnosti podatkov potrebna tudi v konstruktorjih!
SpremeniSpol, SpremeniSerijsko • Kaj pa SpremeniSpol • Če niste v kakšni čudni industriji ali razvoju, je ta metoda odveč ;-)) • Morda tudi metoda SpremeniSerijsko • Pozor na konstruktor brez parametrov • Serijska je "NEDOLOČENO" • Metoda SpremeniSerijsko naj pusti spreminjati le take serijske številke! public bool SpremeniSerijsko(string seStev) { // sprememba dopustna le, če serijske štev. ni if (this.serijska.Equals("NEDLOČENO")) { this.serijska = seStev; return true; } return false; // ne smemo spremniti že obstoječe! }
Dostop do stanj Poizvedba “spremenljivka” v izrazu zajcek.PovejTezo() Da bomo lahko izvedeli težo zajca Najenostavneje v telesu metode le return this.masa; Lahko stvar "oblikujemo" – recimo, da bomo uporabniku vedno povedali le težo na pol kilograma, mi pa bomo interno stvar vodili natančneje
Razred Zajec - povejTezo public double PovejTezo() { return this.masa; // ali return masa } Ali pa prilagodimo podatke Težo povemo na 0.5 kg natančno 2.721 2.5, 2.905 3, 2.502 2.5, ... Vzamemo težo v celih kg in pogledamo prvo decimalko decimalnega dela Če je med 3 in 7, prištejemo k celim kg 0.5 Če je več kot 7, prištejemo k celim kg 1.0 public double PovejTezo() { // težo bomo povedali le na 0.5 kg natančnoint tezaKg = (int)this.masa; int decim = (int)((this.masa – tezaKg) * 10); if (decim < 3) return tezaKg + 0.0; if (decim < 8) return tezaKg + 0.5; return tezaKg + 1.0; }
Celotni razred Zajec - 1 public class Zajec { private string serijska; private bool spol; private double masa; // konstruktor public Zajec() { this.spol = true; // vsem zajcem na začetku določimo m. spol this.masa = 1.0; // in tehtajo 1kg this.serijska = "NEDOLOČENO"; } public Zajec(string serijskaStev):this() { this.serijska = serijskaStev; } public Zajec(string serijskaStev, bool spol, double masa):this() { this.serijska = serijskaStev; this.SpremeniTezo(masa); // uporabimo metodo za sprem. this.spol = spol; }
Celotni razred Zajec - 2 public double PovejTezo() { // težo bomo povedali le na 0.5 kg natančno int tezaKg = (int)this.masa; int decim = (int)((this.masa – tezaKg) * 10); if (decim < 3) return tezaKg + 0.0; if (decim < 8) return tezaKg + 0.5; return tezaKg + 1.0; } public bool SpremeniTezo(double novaTeza) { // smislena nova teza je le med 0 in 10 kg if ((0 < novaTeza) && (novaTeza <= 10)){ masa = novaTeza; // this.masa ... Lahko pa this spustimo! return true; // sprememba uspela } // v nasprotnem primeru NE spremenimo teže // in javimo, da spremembe nismo naredili return false; }
Celotni razred Zajec - 3 public string PovejSerijsko() { return this.serijska; } public void SpremeniSerijsko(string s) { this.serijska = s; } public bool JeSamec() { return this.spol; } // ker se spol naknadno NE spremeni, metode za // spreminjanje spola sploh ne ponudimo uporabniku! } // Zajec
Uporaba razreda Zajec public class ZajčnikNov { public static void Main(string[] ar) { Zajec z1 = new Zajec("1238-12-0", false, 0.12); if (z1.SpremeniTezo(z1.PovejTezo() + 0.3)) Console.WriteLine("Teža je spremenjena na " + z1.PovejTezo()); else Console.WriteLine("Teža je nespremenjena!" + " Prirastek je prevelik! Preveri!"); Console.WriteLine("Zajec ima ser. št.:" + z1.PovejSerijsko()); } } public class Zajčnik { public static void Main(string[] ar) { Zajec z1 = new Zajec(); z1.serijska = "1238-12-0“; z1.spol = false; z1.masa = 0.12; z1.masa = z1.masa + 0.3; System.out.println("Zajec ima ser. št.:” + z1.serijska); }}
Ostale metode Poleg get/set metod in konstruktorjev Metode Odzivi objektov "znanje objektov" Objekti tipa string Znajo povedati, kje se v njih začne nek podniz: "niz".IndexOf("i") Znajo vrniti spremeniti črke v male in vrniti nov niz: nekNiz.ToLower() Znajo povedati, če so enaki nekemu drugemu nizu: mojPriimek.Equals("Lokar") "naši" razredi Sprogramiramo znanje – ustrezne metode Zajec bo znal povedati svojo vrednost, če mu povemo ceno za kg žive teže
Razred Zajec – dodatne metode public double Vrednost(double cenaZaKg) { // pove vrednost zajca // zajce tehtamo na dogovorjeno natančnost return cenaZaKg * this.PovejTezo(); } public bool MeNapojiti() { // ugotovimo, če ga je smiselno // napojiti, da bomo "ujeli" naslednjih pol kg // dejanska teža je večja od "izmerjene" return (this.masa – this.PovejTezo() > 0); }
Metoda ToString Poglejmo si naslednji program: using System; using MojaKniznica; namespace Izpis { class Program { public static void Main(string[] args) { Zajec zeko = new Zajec(); Console.WriteLine("To je zajec: " + zeko); Console.Write("Press any key to continue . . . "); Console.ReadKey(true); } } }
ToString • Očitno objekte lahko tudi izpišemo • Gre seveda tudi takole • string niz = "Zajec " + zeko + "!"; • Torej se tudi objekti "obnašajo" tako kot int, double ... (se torej pretvorijo v niz) • A s pretvorbo nismo ravno zadovoljni, radi bi kakšne bolj smiselne informacije • V razredu, ki ga definiramo (recimo Zajec) napišemo metodo ToString • Če na določenem mestu potrebujemo niz, a naletimo na objekt, se ta metoda pokliče avtomatično • string niz = "Zajec " + zeko.ToString() + "!";
Metoda ToString Isti program, a tako, da je v razredu Zajec metoda ToString: using System; using MojaKniznica; namespace Izpis { class Program { public static void Main(string[] args) { Zajec zeko = new Zajec(); Console.WriteLine("To je zajec: " + zeko); Console.Write("Press any key to continue . . . "); Console.ReadKey(true); } } }
ToString • V razred Zajec smo napisali public override string ToString() { return "Zajec: " + this.PovejSerijsko(); } • Posebnost - override • Zaradi "dedovanja" • O tem kasneje • Z dedovanjem smo avtomatično pridobili metodo ToString (zato je vedno na voljo) • Zato override, da "povozimo " podedovano metodo
ToString in Opis • Razlika med public override string ToString() { return "Zajec: " + this.PovejSerijsko() ; } • in public string Opis() { return "Zajec: " + this.PovejSerijsko() ; } • Metodo Opis moramo poklicati sami, metoda ToString se kliče avtomatsko (če je potrebno) • string niz1 = "Zajec " + zeko.ToString() + "!"; • string niz2 = "Zajec " + zeko + "!"; • string niz3 = "Zajec " + zeko.Opis() + "!"; • Vsi trije niz enaki! • ToString obstaja, tudi, če jo ne napišemo (a verjetno z vrnjenim nizom nismo najbolj zadovoljni)
Tudi objekti so lahko del razreda • Ko sestavljamo razred, kot objektne spremenljivke lahko uporabimo tudi spremenljivke istega razreda • Npr.: starsi Zajca • Razred Clan • public class Clan { • private string ime; • private Clan gaJePriporocil; • ...
Še malo o zajcih • Preden nadaljujemo • Želimo hraniti tudi starše zajca public class Zajec { private double masa; private string serijska; private bool spol; private Zajec oce; private zajec mati; • Še konstruktor
Problemi s konstruktorjem • Sestavimo privzeti konstruktor public Zajec() { this.spol = true; this.masa = 1.0; this.serijska = "NEDOLOČENO"; this.oce = new Zajec(); this.mama = new Zajec(); } • Ko stvar prevedemo, je vse v redu. A ob poskusu • Zajec rjavko = new Zajec();
Problemi s konstruktorjem • Rekurzija brez ustavitve • Tudi konstruktor je metoda • Ustavitveni pogoj • A pri konstruktorju brez parametrov ni parametrov, ki bi lahko določili ustavitveni pogoj
Kaj storiti • "Privzeti" zajec ne pozna staršev • oce = null; • mama = null; • Če malo pomislimo – ko zajca "naredimo", morata starša že obstajati • Ju nima smisla ustvarjati na novo