Professional Documents
Culture Documents
C#
Osnove
objektnega
programiranja
Gregor Jere, Matija Lokar in Sreo Urani
V 0.9
marec 2009
C# . NET
Programiranje 1 VS Informatika
C# . NET
Programiranje 1 VS Informatika
C# . NET
Predgovor
Omenjeno gradivo pokriva osnove objektnega programiranja v C# .
Gradivo vsekakor ni dokonano in predstavlja delovno razliico. V njem so zagotovo napake (upava, da
immanj), za katere se vnaprej opraviujeva. Da bo laje spremljati spremembe, obstaja razdelek Zgodovina
sprememb, kamor bova vpisovala spremembe med eno in drugo razliico. Tako bo nekomu, ki si je prenesel
starejo razliico, laje ugotoviti, kaj je bilo v novi razliici spremenjeno.
Programiranje 1 VS Informatika
C# . NET
Zgodovina sprememb
14. 11. 2008: Razliica V0.8 le prenos (e neurejeno) Matijevega, Gregorjevega (str. 1 120) in Saovega
gradiva. Premisliti je e potrebno kaj in kako.
5. 3. 2009: Razliica V0.9 e vedno povsem neurejeno. Dodano nekaj gradiva, ki ga je smiselno vkomponirati.
Gradivo dodano na konec in sicer:
Vsebina prosojnic, ki naj bi bile spredavane letos
Zgled za Avto
Gradivo, ki pokriva uvod v OOP iz C++. Tam je nekaj smiselnih zgledov, ki pa jih je potrebno prepisati v
C#.
Programiranje 1 VS Informatika
C# . NET
KAZALO
Objektno programiranje ...................................................................................................................................... 9
Motivacija ....................................................................................................................................................... 9
Objektno usmerjeno programiranje kaj je to .............................................................................................. 10
Objekti........................................................................................................................................................... 11
Objekti........................................................................................................................................................... 13
Programiranje v C# ....................................................................................................................................... 14
Objekti........................................................................................................................................................... 14
Klasino/objektno programiranje .................................................................................................................. 14
Od kje razredi? .............................................................................................................................................. 15
Objekt in ime spremenljivke ......................................................................................................................... 15
Ustvarjanje objektov ..................................................................................................................................... 15
C# in objekti .................................................................................................................................................. 15
Ustvarjanje objektov ..................................................................................................................................... 16
Zgled ............................................................................................................................................................. 16
Objektno programiranje ................................................................................................................................ 18
Objekti, razredi, ... ............................................................................................................................................ 19
Zdruevanje podatkov ................................................................................................................................... 19
Uporaba razreda Zajec .................................................................................................................................. 21
Dostop do podatkov v objektu ...................................................................................................................... 22
e en primer - Ulomek .................................................................................................................................. 25
Povzetek ........................................................................................................................................................ 26
Konstruktorji ................................................................................................................................................. 26
this ................................................................................................................................................................. 27
Uporaba razreda: ........................................................................................................................................... 28
Privzeti konstruktor ....................................................................................................................................... 28
Ve konstruktorjev ........................................................................................................................................ 29
Preobteene metode ...................................................................................................................................... 29
Konstruktorji razreda Zajec navzkrino sklicevanje .................................................................................. 30
e malo o this ................................................................................................................................................ 30
Zgled ............................................................................................................................................................. 31
Objektne metode ........................................................................................................................................... 34
Zgledi ................................................................................................................................................................ 37
Datum............................................................................................................................................................ 37
Fibonaccijevo zaporedje................................................................................................................................ 38
Vaje ................................................................................................................................................................... 40
Kochova rta ................................................................................................................................................. 40
Razred Toka in Kochova rta ...................................................................................................................... 40
Ulomek .......................................................................................................................................................... 40
Razred Majica ............................................................................................................................................... 40
Razred Zajec ................................................................................................................................................. 41
Razred Kolega ............................................................................................................................................... 41
Uporaba razreda Kolega ................................................................................................................................ 41
Uporaba razreda Zajec .................................................................................................................................. 42
Datum............................................................................................................................................................ 42
Zajci z datumom............................................................................................................................................ 42
Uporaba razreda Zajec z datumom ................................................................................................................ 42
Nadgradimo datum ........................................................................................................................................ 42
Dostop do stanj objekta..................................................................................................................................... 42
Dostopi do stanj ............................................................................................................................................ 43
Zgledi ............................................................................................................................................................ 48
Programiranje 1 VS Informatika
C# . NET
C# . NET
Programiranje 1 VS Informatika
C# . NET
Objektno programiranje
Motivacija
Pri programiranju se je izkazalo, da je zelo koristno, e podatke in postopke nad njimi zdruujemo v celote, ki jih
imenujemo objekte. Programiranje je potem sestavljeno iz tega, da objekte ustvarimo in jim naroamo, da
izvedejo doloene postopke. Veina sodobnih programskih jezikov je objektno ali kot tudi reemo predmetno
usmerjenih. Pri uporabi tovrstnih jezikov hitro naletimo naletimo na pojme kot so zdruevanje (enkapsulacija),
velinost (polimorfizem), dedovanje (inheritenca), ki so vsaj na prvi pogled zelo zapleteni, Nas ne bodo
zanimali, kot tudi ne tevilne druge podrobnosti. Objektno usmerjeno programiranje nam omogoa, da na
problem gledamo kot na mnoico objektov, ki med seboj sodelujejo in vplivajo drug na drugega. Na ta nain
laje piemo sodobne programe, kjer se nenehno odvija veliko tevilo dogodkov kot so premikanje mike,
zapiranje oken, klikanje na gumbe, potrditev doloenih izbir, ki se med sabo prepletajo, vplivajo drug na
drugega in kar bi le s teavo sprogramirali na klasien nain z nizanjem zaporedja stavkov in ukazov.
tevilni jeziki (JavaScript, Visual Basic for Applications, Java, C#, Python, ) nudijo okolja v katerih so e
doloeni objekti, nad katerimi lahko izvajamo doloene metode, funkcije. Tako "iz ni" dobimo grafini objekt g,
na katerim potem z doloeno metodo nariemo krog. Ko program zaenemo, ta samodejno ustvari okno z
doloenim imenom in gumbom za zapiranje
Veina jezikov omogoa, da program zlahka dopolnimo z gumbi, potrditvenimi stikali in podobnimi elementi.
Vse to so objekti, ki imajo lastnosti in metode, s katerimi na te objekte vplivamo.
Na primer v jeziku JavaScript. Zanima nas le oznaeni del
var i = 0;
function animacija() {
i = i + 1;
if (i == 6) i = 1;
document.menjajocaSlika.src = "album" + i + ".jpg";
setTimeout("animacija()", 1000)
}
JavaScript spletno stran, na kateri se nahaja, imenuje kot objekt z imenom document. Na tem objektu imamo
tudi druge objekte, v naem konkretnem primeru sliko (vstavljeno v jeziku HTML z znako IMG), poimenovano
kot menjajocaSlika:
<img name=" menjajocaSlika " src="album1.jpg">
Podobno z metodo writeln vstavimo v samo dototeko ustrezno kodo v jeziku html. e v kodi spletne strani
pie
<script type="text/javascript">
document.writeln("<p>To naj se pojavi na spletni strani!</p>");
</script>
pomeni, da naj se objekt document (kar pomeni kar ta spletna stran) spremeni tako, da vsebuje tekst, zapisan
med narekovaji. Dejansko je torej uinek isti, kot e bi na spletni strani napisali kar
<p>To naj se pojavi na spletni strani!</p>
Seveda pa smo se doslej nauili e dovolj, da vemo, kakne vse monosti s tem imamo verjetno bomo
JavaScript uporabili, da bomo napisali na spletno stran kaj bolj zapletenega, na primer besedilo, ki ga bomo prej
s pomojo ustreznega postopka obdelali. Tako smo na primer pri esti nalogi hitrega testa v uvodu uporabili
monost pisanja na spletno stran zato, da smo na enostaven nain poenotili vse naslove na spletni strani.
Programiranje 1 VS Informatika
C# . NET
10
Ko torej piemo programe, imamo s samim izvajalnim okoljem ponavadi na voljo bogato zbirko razlinih
objektov (natanneje nartov za to, kakni so objekti doloene vrste). Ni nam potrebno pisati na stotine vrstic
kode le za to, da bi dosegli, da na program uporabniku omogoa vnos datuma preko posebnega okna z e
izpisanim koledarjem. Vedeti je potrebno le, da imamo v izvajalnem okolju e na voljo (nart za) tovrstni objekt.
Ostane nam le e, da tak objekt ustvarimo in s pripravljenimi metodami nanj vplivamo.
Tako s spodnjim zgledom v programskem jeziku Java ustvarimo okno z vnosno povrino, po kateri lahko
piemo.
e ne bi imeli na voljo e ustreznih objektov, bi na program sestavljalo na desetine ali celo stotine ustreznih
ukazov. Tako pa le uporabimo dana narta za objekta JFrame in JTextArea, z ukazom new ustvarimo objekta
ustrezne vrste in z metodami, kot so setSize, show in drugimi vplivamo nanju.
import javax.swing.*;
import java.awt.*;
public class JFrameTest {
public static void main(String[] args) {
JFrame okno = new JFrame("Moje okno");
okno.setSize(250, 250);
okno.setLocation(300,200);
okno.getContentPane().add(BorderLayout.CENTER,
new JTextArea(10, 40));
okno.show();
}
}
In seveda imamo na voljo take objekte tudi v standardnih knjinicah jezika C#.
Objektno usmerjeno programiranje nam omogoa, da na problem gledamo kot na mnoico objektov, ki med
seboj sodelujejo in vplivajo drug na drugega. Za nas je pomembno to, da veina sodobnih jezikov prinaa v
svojem izvajalnem okolje celo vrsto e pripravljenih objektov in metod za delo z njimi. Ti objekti so na primer
spletna stran, slika na spletni strani, izbire v menuju programov v okolju Microsoft Office, grafino okno,
tiskalnik, . S pripravljenimi metodami potem vplivamo na te objekte na primer zamenjamo sliko na spletni
strani, spremenimo privzeto delovanje ukaza Print v izbiri File, na grafino povrino nariemo krog,
Objektno usmerjeno programiranje kaj je to
Pri objektno (ali kot tudi reemo predmetno) usmerjenem programiranju se ukvarjamo z objekti seveda.
Objekt je nekakna rna katla, ki dobiva in poilja sporoila. V tej rni katli (objektu) se skriva tako koda (torej
zaporedje programskih stavkov), kot tudi podatki (informacije nad katerimi se izvaja koda). Pri klasinem
programiranju imamo kodo in podatke loene. Tudi mi smo do sedaj programirali ve ali manj na klasien nain.
Pisali smo metode, ki smo jim podatke posredovali preko parametrov. Parametri in metode niso bile prav ni
tesno povezane. e smo npr. napisali metodo, ki je na primer poiskala najveji element v tabeli tevil, tabela in
metoda nista bili zdrueni tabela ni ni vedela o tem, da naj bi kdo npr. po njej iskal najveja tevila.
V objektno usmerjenem (vasih boste sreali tudi kratico OO ali O-O, kar izvira iz object oriented)
programiranju pa sta koda in podatki zdueni v nedeljivo celoto objekt. To prinaa doloene prednosti. Ko
uporabljamo objekte nam nikoli ni potrebno pogledati v sam objekt. To je dejansko prvo pravilo OO
programiranja uporabniku ni nikoli potrebno vedeti, kaj se dogaja znotraj objekta.
Programiranje 1 VS Informatika
C# . NET
11
Objekt
Zakaj ni potrebno vedeti tega? Vsi objekti med samo komunicirajo preko sporoil. Za vsak objekt se tono ve,
kakna sporoila lahko sprejme in kakna lahko polje. Vse, kar objekt zna narediti, je doloeno z vmesnikom
objekta.
Se vam zdi to zapleteno? No, pa povejmo malo bolj "po domae". Gre dejansko zato, da nad objektom izvajamo
razline metode. In za vsak objekt se tono ve, katere metode zanj obstajajo in kakne rezultate vraajo.
Recimo, da imamo doloen objekt z imenom obj, ki predstavlja doloeno osebo in vemo, da ta objekt lahko
povpraamo (mu poljemo sporoilo) o tem, koliko je njegov IQ. To storimo tako, da nad njem izvedemo
metodo
obj.KolikoJeIQ()
Objekt odgovori s sporoilom (metoda vrne rezultat), ki je neko celo tevilo.
Koliko je
tvoj IQ ?
92
Tisto, kar je pomembno, je to, da nam, kot uporabnikom objekta, ni potrebno vedeti, kako objekt izrauna IQ
(je to podatek, ki je zapisan nekje v objektu, je to rezultat nekega preraunavanja ). Kot uporabnikom nam je
vano le, da se z objektom lahko pogovarjamo o njegovem IQ. Vse "umazane podrobnosti" o tem, kaj je znotraj
katle, je prepueno tistim, ki napiejo kodo s pomojo katere se ustvari objekt in (e je zadeva seveda
sprogramirana prav) uporabnik (programer, ki pie drug program, ki te objekte uporablja) se vanje ne more
vtikati.
Seveda se lahko zgodi, da se kasneje ugotovi, da je potrebno "preurediti notranjost objekta". In tu se izkae
prednost OO koncepta. Ker v programih, kjer objekte uporabljamo, ni ne vemo o tem, kaj je znotraj katle, kaj
se na primer dogaja, ko objekt povpraamo po IQ, bodo programi navkljub spremembam znotraj katle e
vedno delovali.
e torej na objekte gledamo kot na rne katle (zakaj rne zato, da se ne vidi, kaj je znotraj!) in z njimi
ravnamo le preko sporoil (preko klicev metod), nai programi delujejo ne glede na morebitne spremembe v
samih objektih.
Omogoanje dostopa do objekta samo preko sporoil in onemogoanje uporabnikom, da vidijo (in brskajo) po
podrobnostih, se imenuje skrivanje informacij (information hidding) ali e bolj ueno enkapsulacija
(encapuslation).
In zakaj je to pomembno? Velja namre, da se programi ves as spreminjajo. Velika veina programov se
dandanes ne napie na novo, ampak se spremeni obstoje program. In veina napak izhaja iz tega, da nekdo
spremeni doloen delek kode, ta pa potem povzroi, da drug del programa ne deluje ve. e pa so tisti delki
varno zapakirani v kapsule, se spremembe znotraj kapsule ostalega sistema prav ni ne tiejo.
Objekti
Objekt je skupek podatkov, s katerim elimo upravljati kot s celoto. Ima:
Podatke:
kaj o objektu vemo, kakne podatke o objektu hranimo
Metode:
Kaj objekt zna
Kakne metode lahko izvajamo nad njem
Vsak objekt pripada nekemu razredu. e pripada objekt x razredu R, potem pravimo tudi da je x objekt tipa R.
Programiranje 1 VS Informatika
C# . NET
12
Pravzaprav smo se e ves as ukvarjali z objekti, saj smo v naih programih uporabljali razline objekte, ki so e
pripravljeni v standardnih knjinicah jezika C#. Oglejmo si nekaj primerov objektov iz standardne knjinice
jezika:
Objekt tipa StreamReader predstavlja vhodni kanal. Kadar elimo brati s tipkovnice ali z datoteke,
naredimo tak objekt in kliemo njegovo metodo readLine za branje ene vrstice.
Objekt System.Console predstavlja standardni izhod. Kadar elimo kaj izpisati na zaslon, pokliemo
metodo Write na objektu System.Console.
Objekt tipa Random predstavlja generator nakljunih tevil. Metoda Next(a, b), ki jo izvedemo nad
objektom tega tipa pa nam vrne neko nakljuno celo tevilo med a in b.
new Random().Next(1,100);
//uporaba metode na objektu iz razreda Random
Console.WriteLine();
//uporaba metode WriteLine na objektu Console
Nauili smo se torej uporabnosti objektnega programiranja, nismo pa se e nauili izdelave svojih razredov.
In e se vrnemo na razlago v uvodu kot uporabniki isto ni ne vemo (in nas pravzaprav ne zanima), kako
metoda Next doloi nakljuno tevilo. In tudi, e se bo kasneje "katla" Random spremenila in bo metoda Next
delovala na drug nain, to ne bo "prizadelo" programov, kjer smo objekte razreda Random uporabljali. Seveda,
e bo sporoilni sistem ostal enak. V omenjenem primeru to pomeni, da se bo metoda e vedno imenovala
Next, da bo imela dva parametra, ki bosta doloala meje za nakljuna tevila in da bo odgovor (povratno
sporoilo) neko nakljuno tevilo z elenega intervala.
Seveda pa nismo omenjeni le na to, da bi le uporabljali te "rne katle", kot jih pripravi kdo drug (npr. jih
dobimo v standardni knjinici jezika). Objekti so uporabni predvsem zato, ker lahko programer definira nove
razrede in objekte, torej sam ustvarja te nove rne katle, ki jih potem on sam in drugi uporablja.
Oglejmo si primer programa v C#, ki uporablja objekte, ki jih napiemo sami.
PRVI
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
OBJEKTNI PROGRAM
using System;
public class MojR {
private string mojNiz;
public MojR(string nekNiz) {
mojNiz = nekNiz;
}
public void Izpisi() {
Console.WriteLine(mojNiz);
}
}
public class Pozdrav {
public static void Main(string[] arg)
{
MojR prvi = new MojR("Pozdravljen, moj prvi objekt v C#!");
prvi.Izpisi();
}
}
Programiranje 1 VS Informatika
C# . NET
13
Program napiimo kar na obiajni nain v okolju SharpDevelop torej New Solution/Windows
Applications/Console Application. Vnesene vrstice kar vse pobriimo in napiimo zgornjo kodo. Ko program
prevedemo in poenemo, dobimo
Objekti
o stanja:
Programiranje 1 VS Informatika
C# . NET
o
o
14
Odzivanje na dogodke
Zdrueno v celoto
oga:
Podatki: velikost, barva, poloaj v prostoru,
Metode: sprememba velikosti, sprememba poloaja,
Ulomek:
Podatki: tevec, imenovalec
Metode: spremeni tevec, spremeni imenovalec, setej, obratna vrednost, lepo izpii, ...
Razlika med ogo kot idejo oge in mojo ogo (konkretni primerek realizacija ideje oge) oziroma
med ulomkom kar tako in ulomkom .
Programiranje v C#
Sestavljanje razredov:
Opis lastnosti objektov
Opis metod (znanja objektov):
Razred je abstraktna definicija objekta in e elimo nek razred uporabiti, mora obiajno obstajati vsaj en
primerek razreda. Primerek nekega razreda imenujemo objekt. Ustvarimo ga s kljuno besedo new.
ImeRazreda primerek = new ImeRazreda();
Objekt je raunalniki model predmeta ali stvari iz vsakdanjega ivljenja (avto, oseba, datum). Za reitev
problema uvedemo mnoico objektov, ki si medsebojno poiljajo sporoila. Lastnosti objektov so zapisane v
razredih (class), ki vsebujejo:
podatke in ,
C# . NET
15
f(x);
Objektno:
x.f();
Od kje razredi?
Veliko razredov je e vgrajenih (so v standardnih knjinicah) v C# in njegovo oklolje. Taki razredi so na primer
Math, System, StreamReader,
o .NET Framework
System, System.IO
Drugi programerji
NekiObjekt a;
new NekiObjekt();
a = new NekiObjekt();
Ustvarjanje objektov
Razred je ablona, ki definira spremenljivke in metode skupne vsem objektom iste vrste.
class:
Ustvarimo ga z new
NekiObjekt a;
Objekt NE obstaja
a je IME objekta
natanneje
a je ime spremenljivke, kjer hranimo NASLOV objekta vrste NekiObjekt
C# in objekti
Razred (class) je opis vrste objekta (nart, kako naj bo objekt videti) opis ideje objekta.
Primerek razreda (instanca) konkretni objekt.
Programiranje 1 VS Informatika
C# . NET
16
Ustvarjanje objektov
Ulomek ime;
ime = new Ulomek(3, 4);
ime: _2h11b11__
o
o
2h11b11:
Nizi
string a = "bla";
string a = new string("bla");
Tabele
int[] tabela = {1, 2, 3};
int[] tabela = new int[3];
tabela[0] = 1;
Zgled
Poglejmo si e en zgled. Denimo, da bi radi napisali program, ki bo prebral nek ulomek in mu pritel 1/2.
"Klasino" se bomo tega lotili takole (seveda pisec ni pozabil, kako se setevajo ulomki, a takojle, po Janezkovo,
si je laje zapomniti ;-) )
POVEAJMO
1:
2:
3:
4:
5:
6:
ULOMEK KLASINO
using System;
namespace UlomkiKlasika {
class Program
{
public static void Main(string[] args)
{
Programiranje 1 VS Informatika
C# . NET
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
17
// vnos podatkov
Console.Write("tevec ulomka: ");
string beri = Console.ReadLine();
int stevec = int.Parse(beri);
Console.Write("Imenovalec ulomka: ");
beri = Console.ReadLine();
int imenovalec = int.Parse(beri);
// "delo"
stevec = stevec + 1;
imenovalec = imenovalec + 2;
// izpis
Console.WriteLine("Nov ulomek je: " + stevec
imenovalec);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}
"
"
Sedaj pa to naredimo e "objektno". Oitno bomo potrebovali razred Ulomek. Objekt tipa Ulomek hrani
podatke o svojem tevcu in imenovalcu. Njegovo znanje je, da "se zna" poveati za drug ulomek. To pomeni, da
vsebuje metodo, ki ta ulomek povea za drug ulomek.
Shematsko bo program (kjer so doloeni deli skriti) videti kot
POVEAJMO
ULOMEK
OBJEKTNO
C# . NET
18
31:
public Ulomek(int st, int im) {
32:
this.stevec = st;
33:
this.imenovalec = im;
34:
}
35:
36:
public void Pristej(Ulomek a) {
37:
this.stevec = this.stevec + a.stevec;
38:
this.imenovalec = this.imenovalec + a.imenovalec;
}
39:
40:
}
41:
class Program
42:
{
43:
public static void Main(string[] args)
44:
{
45:
// vnos podatkov
46:
Console.Write("tevec ulomka: ");
47:
string beri = Console.ReadLine();
48:
int stevec = int.Parse(beri);
49:
Console.Write("Imenovalec ulomka: ");
50:
beri = Console.ReadLine();
51:
int imenovalec = int.Parse(beri);
52:
Ulomek moj = new Ulomek(stevec, imenovalec);
53:
// "delo"
54:
Ulomek polovica = new Ulomek(1, 2);
55:
moj.pristej(polovica);
56:
// izpis
57:
Console.WriteLine("Nov ulomek je: " + moj.stevec + " / " +
58:
moj.imenovalec);
59:
}
60: }
61: }
e posebej oznaimo kljune toke (poleg definicije razreda Ulomek v vrsticah 4 17):
Objektno programiranje
Imamo nek problem. Kako se torej lotiti nartovanja reitve s pomojo objektnega programiranja?
Programiranje 1 VS Informatika
C# . NET
19
serijsko tevilko
spol
teo
Kako dosei, da se podatki drijo skupaj:
Tabela ni ustrezna
Tabela je zbirka istovrstnih podatkov
Pri tabelah smo omenili, da so sestavljen podatkovni tip. Vsebujejo elemente istega tipa. Velikokrat pa elimo
ustvariti tip, ki je prav tako sestavljen, a iz razlinih podatkovnih tipov.
V ta namen imamo v jeziku C# tako imenovane strukture. A ker gre v bistvu le za posebni primer objektov, jih
bomo kar preskoili in si raji kar neposredno ogledali objekte. Da pa boste vedeli zakaj gre, e boste v kaknem
programu naleteli na kljuno besedo struct, si zapomnimo le, da gre za nekakne "poenostavljene" objekte.
V zgledih do sem smo razrede pisali le za "lokalno uporabo", znotraj doloenega programa. Sedaj se nauimo
e, kako na najlaji nain gradimo svojo knjinico razredov, ki jih bomo uporabljali v razlinih programih. Na ta
nain bomo tudi bolj loili tisti del programiranja, ko gradimo razrede in tisti del, ko uporabljamo objekte
doloenega razreda.
V okolju SharpDevelop tokrat ne izberemo Windows Applications/Console Application, ampak C# / Class Library
Programiranje 1 VS Informatika
C# . NET
20
Kot ime bomo napisali MojiRazredi. V ta projekt bomo dodajali vse tiste razrede, ki jih bomo ustvarjali,
vkljuno z naim razredom Zajec.
Vidimo, da je SharpDevelop pripravil okolje in naredil tako imenovam imenski prostor MojiRazredi. Znotraj
tega imenskega prostora bomo zlagali nae razrede. Ker nam ime MyClass ni ve, bomo to spremenili v
Zajec.
Omenimo e komentarje, ki se zano z ///. To so tako imenovani dokumentacijski komentarji. Ti sluijo za to, da
pripravimo dokumentacijo o razredu. Ta je zelo pomembna, saj nosi tisto informacijo, ki jo kasneje
potrebujemo, e elimo razred uporabljati. Zanekrat si zapomnimo le, da na ustrezno mesto napiemo kratek
povzetek o tem, emu je razred namenjen. Ve o tem si lahko preberete:
http://www.softsteel.co.uk/tutorials/cSharp/lesson19.html
http://www.winnershtriangle.com/w/Articles.XMLCommentsInCSharp.asp
http://www.csharphelp.com/archives3/archive598.html
...
RAZRED ZAJEC
21: public class Zajec {
22:
public string serijska;
23:
public bool spol;
24:
public double masa;
25: }
Programiranje 1 VS Informatika
C# . NET
21
Ni to konkreten zajec
Ni metode Main, dejansko se NI ne izvede, ... Ni namenjeno poganjanju kot program.
Zato bo stvar potrebno prevesti drugae. V Build izberemo Build Moji Razredi (oziroma pritisnemo na F9). S tem
smo ustvarili ustrezno prevedeno obliko in sicer MojiRazredi.dll. TA vsebuje med drugim tudi definicijo razreda
Zajec.
Uporaba razreda Zajec
Denimo, da sedaj piemo nek program, kjer bomo potrebovali Zajce. V ta namen sedaj sestavimo program v C#.
Obnaamo se tako kot smo pisali programe do sedaj.
v SharpDevelop: File/New Solution/Winows applications/Console Application
Sedaj moramo dodati e t.i. referenco, da bo na program prepoznal na razred.
Project / Add reference
Programiranje 1 VS Informatika
C# . NET
22
V oknu, ki se odpre, izberemo .Net Assembly Browser. Poiemo imenik MojiRazredi/bin/Debug in v njem
datoteko MojiRazredi.dll.
Da bomo kraje pisali, dodamo sedaj imenski prostor MojiRazredi (ker vsebuje definicijo razreda Zajec)
using MojiRazredi;
e sedaj v programu potrebujemo konkretnega zajca, ga ustvarimo z new:
new Zajec()
Ustvaril se je konkreten zajec po navodilih za razred Zajec (ta zajec ima torej tri podatke /
lastnosti / komponente)
rjavko.spol = true;
rjavko.serijska = BRGH_17_A;
rjavko.masa = 3.2;
UPORABA
RAZREDA
ZAJEC
C# . NET
23
FARMAZAJCEV
28: public class FarmaZajcev {
29:
public static void Main(atring[] ar) {
30:
Zajec[] zajci = new Zajec[10]; // na farmi imamo do 10 zajcev
int i = 0;
31:
32:
while (i < 10) {
33:
zajci[i] = new Zajec(); // rodil se je nov zajec
34:
zajci[i].serijska = "1238-12- + i;
35:
zajci[i].spol = false;
zajci[i].masa = 0.12;
36:
37:
i++;
38:
}
...
39:
40:
}
41: }
Programiranje 1 VS Informatika
C# . NET
24
Programiranje 1 VS Informatika
C# . NET
25
e en primer - Ulomek
Denimo, da bi potrebovali e podatkovni tip Ulomek. Na projekt MojiRazredi (seveda bi lahko naredili novo
knjinico razredov) dopolnimo z
RAZRED
ULOMEK
x.imenovalec : enako
x.stevec = 1;
x.imenovalec = x.stevec + 1;
Programiranje 1 VS Informatika
C# . NET
26
No, ne pozabimo, da e doloen razred potrebujemo le v sklopu reitev enega primera, ga lahko ustvarimo tudi
"lokalno", znotraj tistega programa.
PRIMER
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
using System;
public class Vozilo
{
public int letnik;
public string proizvajalec;
public int prevozeniKilometri;
}
class Program
{
public static void Main()
{
Vozilo mojAvto = new Vozilo();//kreiramo primerek
mojAvto.proizvajalec = "Citron";
mojAvto.letnik = 2000;
mojAvto.prevozeniKilometri = 90000;
Console.WriteLine("Proizvajalec: " + mojAvto.proizvajalec);
Console.WriteLine("Letnik: " + mojAvto.letnik);
Console.WriteLine("Kilometri: " + mojAvto.prevozeniKilometri);
}
}
Razlaga. Najprej ustvarimo razred z imenom vozilo (vrstice 2-7). V glavnem programu kreiramo nov primerek
(objekt) z imenom mojAvto razreda Vozilo (vrstica 12). Objektu doloimo vrednosti (vrstice 13-15) in izpiemo
vrednosti (vrstice 16-18).
Povzetek
Najenostavneji razred kreiramo tako, da doloimo spremenljivke, ki doloajo objekte tega razreda. Te so lahko
razlinih podatkovnih tipov. Sintaksa najenostavneje definicije razreda je naslednja:
public class ImeRazreda {
public podatkovni tip element1;
public podatkovni tip element2;
C# . NET
27
RAZRED ZAJEC
S KONSTRUKTORJEM
C# . NET
28
new Zajec()
S tem se je ustvaril konkreten zajec (torej tak, ki ima tri spremenjlivke za hranjenje podatkov), nad katerim smo
takoj potem izvdeli doloeno akcijo po navodilih iz konstruktorja Zajec(). Kombinacija new Zajec()je
torej poskrbela, da ima objekt tipa Zajec tri podatke z vrednostmi, kot je predpisano v konstruktorju.
Privzeti konstruktor
e konstruktorja ne napiemo (kot ga nismo prej), ga naredi prevajalnik sam (a metoda ne naredi ni). Dokler
je bil na razred zajec
RAZRED ZAJEC
1:
2:
3:
4:
5:
PRIVZETI
KONSTRUKTOR RAZREDA
ZAJEC
ULOMEK
ULOMEK
S PRIVZETIM KONSTRUKTORJEM
Programiranje 1 VS Informatika
C# . NET
29
Ve konstruktorjev
Uporabniki bi poleg privzetega zajca, radi e monost, da bi takoj, ko zajca naredijo, temu doloili e
serijsko tevilko. Radi bi torej konstruktor
public Zajec()
to pomeni, da bi imeli ve metod z enakim imenom. Je to sploh mono?
Jezik C# podpria tako imenovano preobteevanje (overloading) metod. Tako imamo lahko znotraj istega
programa ve metod z enakim imenom. To ne velja le za konstruktorje, ampak tudi v splonem.
Metode se morajo razlikovati ne v imenu, ampak podpisu. Podpis metode je sestavljen iz imena metode in
tipov vseh parametrov. Konstruktor
Zajec()
ima torej podpis enostavno Zajec, konstruktor
Programiranje 1 VS Informatika
C# . NET
30
etrti tip objekta v glavno kodo ni potrebno posegati naredimo le novo metodo z istim imenom
(Ploscina) in s parametrom katerega tip je novi objekt. Klic pa je e vedno Ploscina(bla)!
Podpisi metod
Podpis metode:
Podpis: ime + tevilo in tipi parametrov!
Tip rezultata (return tip) NI del podpisa!
KONSTRUKTORJI
62:
63:
64:
65:
66:
67:
68:
69:
70:
RAZREDA
ZAJEC
public Zajec() {
this.spol = true; // vsem zajcem na zaetku doloimo m. spol
this.masa = 1.0; // in tehtajo 1kg
this.serijska = NEDOLOENO;
}
public Zajec(string serijskaStev) : this() {
this.serijska = serijskaStev;
}
C# . NET
31
serijska
this.spol = spol;
Obstajalo je e DRUGO ime spol
Loiti med spremenljivko spol, ki je parameter in lastnostjo objekta z imenom spol
"Prednost" ima bolj "lokalna" stvar torej parameter
spol = spol;
Zgled
Oglejmo si e en primer sestavljanja razredov. Denimo, da bi radi napisali program, ki vodi evidenco o lanih
portnega kluba. Podatki o lanu obsegajo ime, priimek, letnico vpisa v klub in vpisno tevilke (seveda je to
poenostavljen primer). Torej objekt, ki predstavlja lana kluba, vsebuje tiri podatke:
RAZRED CLAN
76: public class Clan {
77:
public string ime;
78:
public string priimek;
79:
public int leto_vpisa;
80:
public string vpisna_st;
81: }
S tem smo povedali, da je vsak objekt tipa Clan sestavljen iz tirih komponente: ime, priimek, leto_vpisa,
vpisna_st.
e je a objekt tipa Clan, potem lahko dostopamo do njegove komponente ime tako, da napiemo a.ime.
Nov objekt naredimo z ukazom new, kot to kae naslednji primer:
TESTKLUB
82: public class TestKlub {
83:
public static void Main(string[] args) {
84:
85:
Clan a = new Clan();
86:
a.ime = "Janez";
87:
a.priimek = "Starina";
a.leto_vpisa = 2000;
88:
89:
a.vpisna_st = "2304";
90:
91:
Clan b = new Clan();
b.ime = "Mojca";
92:
93:
b.priimek = "Mavko";
b.leto_vpisa = 2001;
94:
95:
b.vpisna_st = "4377";
96:
97:
Clan c = b;
98:
c.ime = "Andreja";
99:
100:
Console.WriteLine("Clan a:\n" + a.ime + " "
101:
" " + a.leto_vpisa + " ("
102:
103:
Console.WriteLine("Clan b:\n" + b.ime + " "
104:
" " + b.leto_vpisa + " ("
105:
106:
Console.WriteLine("Clan c:\n" + c.ime + " "
107:
" " + c.leto_vpisa + " ("
108:
Console.ReadLine();
109: }
110: }
Programiranje 1 VS Informatika
+ a.priimek +
+ a.vpisna_st + ")\n");
+ b.priimek +
+ b.vpisna_st + ")\n");
+ c.priimek +
+ c.vpisna_st + ")\n");
C# . NET
32
RAZRED CLAN
110: public class Clan {
111:
public string ime;
112:
public string priimek;
113:
public int leto_vpisa;
114:
public string vpisna_st;
115:
116:
public Clan() {
Programiranje 1 VS Informatika
C# . NET
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129: }
33
Ko sedaj poskusimo izvesti na testni program, teav ni ve in dobimo isti rezultat. A emu smo potem pisali e
drugi konstruktor in zakaj smo se sploh ubadali z njimi, e pa je stvar enaka kot prej. Poglejmo ta testni
program
TESTCLAN
130: public class TestClan{
131:
public static void Main(string[] args) {
132:
Clan a = new Clan("Janez", "Starina", 2000, "2304");
133:
Clan b = new Clan("Mojca", "Mavko", 2001, "4377");
Clan c = b;
134:
135:
c.ime = "Katarina";
136:
137:
Console.WriteLine("Clan a:\n" + a.ime + " " + a.priimek +
138:
" " + a.leto_vpisa + " (" + a.vpisna_st +
")\n");
139:
Console.WriteLine("Clan b:\n" + b.ime + " " + b.priimek +
140:
141:
" " + b.leto_vpisa + " (" + b.vpisna_st +
")\n");
142:
Console.WriteLine("Clan c:\n" + c.ime + " " + c.priimek +
143:
144:
" " + c.leto_vpisa + " (" + c.vpisna_st + ")\n");
145:
}
146: }
Zgornji program deluje povsem enako kot prejnji testni program, je pa vsekakor bolj pregleden. Namen
konstruktorja je, da nastavi vrednosti komponent objekta. Ker konstruktorji (pa tudi druge metode znotraj
razreda) zelo pogosto dostopajo do komponent, nam C# omogoa, da namesto this.komponenta piemo
kar komponenta:
C# . NET
134:
135:
147:
136:
137:
138:
139:
140:
141:
142: }
34
Objektne metode
Svoj pravi pomen dobi sestavljanje razredov takrat, ko objektu pridruimo e metode, torej znanje nekega
objekta. Kot e vemo iz uporabe vgrajenih razredov, metode nad nekim objektom kliemo tako, da navedemo
ime objekta, piko in ime metode. Tako e elimo izvesti metodo WriteLine nad objektom System.Console
napiemo
besedilo.Equals(primerjava)
in tako dalje. Denimo, da potrebujemo metodo, ki vrne inicialke nekega lana. To bomo napisali takole:
TESTCLAN
151: public class TestClan{
152:
public static void Main(string[] args) {
Clan a = new Clan("Janez", "Starina", 2000, "2304");
153:
string inicialnkeClanaA = a.Inicialke();
154:
155:
Console.Write("Clan a:\n" + a.ime + " " + a.priimek +
156:
" " + a.leto_vpisa + " (" + a.vpisna_st + ")
");
157:
Console.WriteLine("ima inicialke: " + inicialnkeClanaA);
}
158:
159: }
Denimo, da smo kasneje ugotovili, da bi bili uporabniki razreda Clan veliko bolj zadovoljni, e bi metoda
Inicialke vrnila niz brez pik, le s presledkom med zaetnico imena in priimka. Kaj storiti?
Potrebno je popraviti le razred Clan, kjer spremnimo metodo
C# . NET
35
Vemo, da z
a = b;
kjer sta a in b obe spremenljivki tipa Clan, v a ne shranimo kopije objekta b, ampak sedaj a in b oznaujeta isti
objekt.
Zato napiimo metodo, ki naredi kopijo objekta.
a = b.Kopija();
V a je nov objekt, ki pa ima iste podatke kot b.
KOPIJA
OBJEKTA
IZPIS
OBJEKTA
OPIS
OBJEKTA
RAZRED CLAN
181: public class Clan {
182:
public string ime;
183:
public string priimek;
184:
public int leto_vpisa;
185:
public string vpisna_st;
186:
187:
public Clan() {
188:
ime = "Ne vem";
189:
priimek = "Ne vem";
190:
leto_vpisa = 0;
191:
vpisna_st = "Ne vem";
192:
}
193:
194:
public Clan(string i, string p, int l, string v) : this() {
195:
ime = i;
196:
priimek = p;
197:
leto_vpisa = l;
Programiranje 1 VS Informatika
C# . NET
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224: }
36
vpisna_st = v;
}
public string Inicialke() {
return this.ime[0] + "." + this.priimek[0] + ".";
}
public Clan Kopija() {
Clan nov = new Clan();
nov.ime = this.ime;
nov.priimek = this.priimek;
nov.leto_vpisa = this.leto_vpisa;
nov.vpisna_stevilka = this.vpisna_stevilka;
return nov;
}
public void Izpis() {
Console.WriteLine("Clan:\n" + this.ime + " " +
this.priimek + " " + this.leto_vpisa +
" (" + this.vpisna_st + ")\n");
}
public string Opis() {
return this.ime + " " + this.priimek + " " +
this.leto_vpisa + " (" + this.vpisna_st + ");
}
Programiranje 1 VS Informatika
C# . NET
37
Zgledi
Datum
Denimo, da v naih programih pogosto delamo z datumi. Zato bomo sestavili ustrezni razred. Najprej
moramo pripraviti nart razreda. Odloiti se moramo torej, kako bi hranili podatke o datumu. Podatki, ki
sestavljajo datum, so:
o dan (tevilo)
o mesec (izbira: tevilo ali pa niz)
o Leto (tevilo)
Denimo, da se odloimo, da bomo dan in leto hranili kot tevilo, mesec pa kot niz (torej kot januar, februar, ...).
Sedaj se moramo odloiti, katere metode bo poleg konstruktorjev poznal na razred. Nekaj idej:
o Lepo izpii
o Poveaj za 1 dan
o Je datum smiselen
o Je leto prestopno
o Nov datum za toliko in toliko dni pred/za danim datumom
o Dan v tednu
o ...
Potem, ko smo si pripravili nart, se lotimo sestavljanja razreda
RAZRED DATUM
241: public class Datum {
242:
public int dan;
243:
public string mesec;
public int leto;
244:
245:
public Datum() {
246:
dan = 1;
247:
mesec = "januar"
248:
leto = 2000;
} // privzeti datum je torej 1.1.2000
249:
Dodajmo e dva konstruktorja
250:
251:
252:
253:
254:
255:
256:
257:
Sedaj se lahko lotimo metod. Kot prvno, nas zanima, ali je leto prestopno
Programiranje 1 VS Informatika
C# . NET
38
JE
Programiranje 1 VS Informatika
C# . NET
39
RAZRED POSPLOENIFIBONACCI
291: public class PosploseniFibonacci {
292: public int prvo;
293: public int drugo;
294:
295: public PosploseniFibonacci() {
296:
this.prvo = 1;
297:
this.drugo = 1;
298: }
299:
300: public PosploseniFibonacci(int p, int d) {
301:
this.prvo = p;
302:
this.drugo = d;
303: }
Metoda bo enostaven primer uporabe rekurzije
C# . NET
40
329: }
330: }
Vaje
Kochova rta
Pri prvi podtoki naloge 1 se koordinati x in y nista "drali" skupaj. Zato sestavi
razred, ki vsebuje koordinato x in y in metodo iz naloge 1 prepii tako, da bo imela
tri parametre: n (stopnjo rte), T1 in T2 (ki sta tipa Tocka, ki si ga ravno sestavil).
Ulomek
Napii testni program, ki naredi tabelo 100 razlinih majic. Potem prepii to
tabelo v datoteko tako, da podatke o vsaki majici zapie v svojo vrstico.
Programiranje 1 VS Informatika
C# . NET
41
spol
Sestavi program, ki naredi tri zajce s teami, ki so nakljuna tevila med 1.2
in 5.5. Izpii vse tri tee zajcev. Enemu poveaj njegovo teo za 2kg. Izpii
serijsko tevilko najlajega zajca.
Razred Kolega
ime
priimek
telefonska tevilka
Sestavi testni program, v katerem ustvari dva objekta tipa Kolega. Oba
objekta tudi izpii na zaslon.
Uporaba razreda Kolega
C# . NET
42
najtejega
najcenejega
vse zajklje
najtejega samca
Datum
Razred Zajec nadgradi tako, da bo za vsakega zajca tudi hranil datum, klo
se je skotil in datum, ko je bil zadnji pregledan.
Uporaba razreda Zajec z datumom
Ustvari farmo zajcev in na njej poii vse tiste zajce, ki v tem koledarskem letu e niso bili pregledani. Nato pa
izpii e tiste zajklje, ki so bile se skotile v obdobju enega leta (torej med 23. 1. 2007 in 22. 1. 2008.
Nadgradimo datum
Lepo izpii
Poveaj za 1 dan
Je datum smiselen
Je leto prestopno
Vrni nov datum za toliko in toliko dni pred danim datumom
Vrni nov datum za toliko in toliko dni za danim datumom
Vrni dan v tednu
...
Programiranje 1 VS Informatika
C# . NET
43
Torej bomo, kot smo omenjali e v uvodu, objekt res imeli za "rno katlo", torej njegove notranje zgradbe ne
bomo "pokazali javnosti". Zakaj je to dobro? e malo pomilsimo, uporabnika razreda pravzaprav ne zanima,
kako so podatki predstavljeni. e podamo analogijo z realnim svetom:
Ko med vonjo avtomobila prestavimo iz tretje v etrto prestavo, nas ne zanima, kako so prestave
realizirane. Zanima nas le to, da se stanje avtomobila (prestava) spremeni. Ko kupimo nov avto
nam je naeloma vseeno, e ima ta drugano vrsto menjalnika, z drugano tehnologijo.
Pomembno nam je le, da se nain prestavljanja ni spremenil, da e vedno v takih in takoh
okoliinah prestavimo iz tretje v etrto prestavo.
S "skrivanjem podrobnosti" omogoimo, da e pride do spremembe tehnologije se za uporabnika se stvar ne
spremeni. V naem primeru programiranja v C# bo to pomenilo, da e spremenimo razred (popravimo
knjinico), se za uporabnike razreda ne bo ni spremenilo.
Denimo, da so v C# 3.0 spremenili nain hranjenja podatkov za doloanje nakljunih tevi v objektih razreda
Random. Ker dejansko nimamo vpogleda (neposrednega dostopa) v te spremenljivke, nas kot uporabnike
razreda Random ta sprememba ni ne prizadane. Programe e vedno piemo na enak nain, kliemo iste
metode. Skratka - ni potrebno spreminjati programov, ki razred Random uporabljajo.e posebej je pomembno,
da programi, ki so delovali prej, e vedno delujejo (morda malo bolje, hitreje, a bistveno je, da delujejo enako).
In e enkrat .- s tem ko "ne dovolimo" vpogleda v zgradbo objekta, lahko poskrbimo za zaito pred
nedovoljenimi stanji. Do sedaj smo spremenljivke, ki opisujejo objekt, kazali navzven (imele so doloilo public).
To pomeni, da uporabnik lahko neposredno dostopa do teh spremenljivk in morebiti objekt spravi v nemogoe
stanje:
mojAvto.prestava = -10;
Dostopi do stanj
Do sedaj smo pisali programe tako, da smo naredili objekt. Ko smo eleli v objekt zapisati kak podatek, smo
uporabili zapis
ime_objekta.stanje = <izraz>;
DOSTOP
DO PODATKOV
RAZRED CLAN
C# . NET
349:
350:
351:
44
}
return false; // leto ni smiselno, ne spremenimo ni in vrnemo false
}
352: }
In e zgled uporabe tega razreda
SPREMINJANJE
Z METODO
Sedaj v 7. vrstici ne bomo podatka popravili na napanega, ker letnica ni ustrezna, v 8. vrstici pa je bila
sprmememba uspena. e bi eleli, bi to, ali je sprememba uspela, lahko tudi preverili tako, da bi pogledali,
kakno vrednost je vrnila metoda.
Po drugi strani pa e iz vrstice 6 vidimo, da je naa "zaita" zelo pomanjkliva. e bi napisali e
361:
novClan.leto_vpisa = 20008;
ime_objekta.stanje = <izraz>;
in bi se stanje spremenljivk, ki opisujejo objekt lahko spreminjalo le preko metod, bi lahko poskrbeli, da bi pred
spremembo podatka izvedli ustrezne kontrole in v primeru poskusa nastavljanja napanih podatkov ustrezno
reagirali.
Po drugi strani pa tudi ni dobro, da se ime_objekta.stanje pojavi kjerkoli. Denimo, da imamo v nekem
programu napisano
RAZRED CLAN
Z DATUMOM
C# . NET
45
378:
datum_vpisa = d;
379:
vpisna_st = v;
380:
}
381:
public string Inicialke() {
382:
383:
return this.ime[0] + "." + this.priimek[0] + ".";
384:
}
385:
public Clan Kopija() {
386:
387:
Clan nov = new Clan();
388:
nov.ime = this.ime;
389:
nov.priimek = this.priimek;
390:
nov.datum_vpisa = this.datum_vpisa.Kopija();
391:
nov.vpisna_stevilka = this.vpisna_stevilka;
392:
Return nov;
393:
}
394:
395:
public void Izpis() {
Console.WriteLine("Clan:\n" + this.ime + " " +
396:
397:
this.priimek
+
"
"
+
this.Datum_vpisa.OpisDat() +
398:
" (" + this.vpisna_st + ")\n");
399:
}
400:
401:
public string Opis() {
402:
return this.ime + " " + this.priimek + " " +
this.datum_vpisa.OpisDat() + " (" + this.vpisna_st + ");
403:
404:
}
405:
public bool SpremeniLetoVpisa(int l) {
406:
if ((2000 <= leto) && (leto <= 2020)) {
407:
this.datum_vpisa.leto = l;
408:
return true; //leto je smsielno, popravimo stanje onbjekta in vrnemo
true
409:
410:
411:
}
return false; // leto ni smsielno, ne spremnimo in in vrnemo false
}
412: }
Preden nadaljujemo, opozorimo na vrstico 29. e bi tam napisali
nov.datum_vpisa = this.datum_vpisa;
bi bilo to narobe. V novem objektu bio namre ne hranili novega datuma, ampak bi le kazali na isti datum, kot
ga vsebuje obstojei objekt. In e bi potem kasneje spremnili datum v kateremoli od teh objektov, bi se spremil
za oba objekta, saj gre za isti datum. Zato smo v 29. vrstici naredili tudi kopijo datuma!
Dodatno razlago morda zahtevata e zapisa
this.datum_vpisa.Kopija();
in
this.Datum_vpisa.OpisDat()
Pa ni ni udnega. this pa oznauje objekt, nad katerim bomo izvajali metodo. Ta objekt ima polje
datum_vpisa. This.datum_vpisa je torej objekt tipa Datum. V tem razredu imamo metodi Kopija() in OpisDat(),
ki ju izvedemo nad tem objektom.
Pri vrstici 45
this.datum_vpisa.leto = l;
je podobno. this.datum_vpisa je objekt tipa Datum, torej ima polje leto.
Programiranje 1 VS Informatika
C# . NET
46
Vrnimo se k razlagi, zakaj ni dobro, da je uporabnik razreda Clan v svojem programu napisal npr.
RAZRED CLAN
426:
427:
428:
}
return false; // leto ni smsielno, ne spremnimo in in vrnemo false
return this.leto_vpisa;
429: }
"Pametni" uporabniki naega razreda bi potem seveda programirali z
METODA VRNILETOVPISA
V RAZREDU
430:
431:
432:
CLAN
Z DATUMOM
return this.datum_vpisa.leto;
Ker je metoda VrniLetoVpisa "na zunaj" (torej za uporabnike) enaka kot prej, programi, kli so jo uporabljali,
delujejo pravilno.
Problem pa je v besedi "pametni uporabnik". Namre pri tako sestavljenem razredu nihe ne prepreuje
uporabniku, da ne bi napisal kar
ime_objekta.stanje
naj sploh ne bi nikoli uporabljali. Zakaj je to lahko problem?
zunanji uporabnik nastavi napano vrednost:
z1.masa = -100.10;
Uporabnik pozna predstavitev:
Kasneje je ni mogoe spremeniti
No na sreo pa imamo monost, da dostop do spremenljivk lahko nadziramo. V C# poznamo 4 naine dostopa:
public
private
Programiranje 1 VS Informatika
C# . NET
47
protected
internal
Zadnjih dveh mi ne bomo uporabljali, zato si njihov pomen in uporabo oglejte kar sami. Dostop public smo e
ves as uporabljali, saj smo pisali na primer:
o
o
Besedi public pomenita, da do teh dveh spremenljivk dostop ni omejen (je javen public). e tega ne elimo ,
public zamenjamo s private
o private string serijska;
o private int[] tab;
o private Datum datumRojstva;
Vasih besedo, ki oznauje nain dostopa (javen ali privaten) spustimo in napiemo le
o bool spol;
Kaken dostop velja takrat, je odvisno od okoliin. Obiajno bo to kar public, ne pa vedno. Zato se opuanju
navedbe dostopa izogibajmo in ga piimo vedno. Zakaj bi zgubljali as s premiljevanjem o tem, v kaknih
okoliinah je ta spremenjlivka in kaken bo potem dostop do nje.
Oglejmo si sedaj razliko med public in private. Zavedati pa se moramo, da znotraj razreda (torej ko sestavljamo
razred in piemo njegove metode) ni omejitev, vedno (ne glede na nain dostopa) je moen dostop do
komponent.
Omejitve pri nainu dostopa veljajo le, ko objekte doloenega razreda uporabljamo torej v drugih programih
in razredih!
public
e je nain dostopa nastavljen na public, to pomeni, da do lastnosti (komponent, spremnljivk, polj ...) lahko
dostopajo vsi, od kjerkoli (iz katerihkoli datotek (razredov)) in sicer z
ime_objekta.lastnost
Denimo, da smo v razredu MojObjekt napisali
public int javnaLastnost;
Kdorkoli naredi objekt vrste MojObjekt:
MojObjekt x = new MojObjekt();
lahko dostopa do javnaLastnost:
x.javnaLastnost
Ta nain smo uporabljali do sedaj.
private
Dostop private pomeni, da do lastnosti ne more dostopati nihe, razen metod znotraj razreda. Ko piemo nart
razreda, sevedda lahko napiemo
this.lastnost
lastnost
Denimo, da smo v razredu MojObjekt napisali
private int privatnaLastnost;
e kdo naredi objekt vrste MojObjekt:
MojObjekt x = new MojObjekt();
Programiranje 1 VS Informatika
C# . NET
48
RAZRED ZAJEC
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
RAZRED ZAJEC2
159: public class Zajec2 {
160:
public string serijska; // serijska stevilka zajca
161:
public bool spol; // true = moski, false = zenska
private double masa; // masa zajca ob zadnjem pregledu
162:
163:
164:
public SpremeniTezo(double x) {
165:
this.masa = x;
166: }
167:
168: }
C# . NET
49
Potrebujemo torej:
Metode za dostop do stanj (za dostop do podatkov v objektu)
Metode za nastavljanje stanj (za spreminjanje podatkov o objektu)
Prvim pogosto reemo tudi "get" metode (ker se v razredih, ki jih sestavljajo angleko usmerjeni pisci, te
1
metode pogosto prino z Get (Daj) ). Druge pa so t.i. "set" metode (set / nastavi) .
Ponovimo e enkrat, zakaj je pristop z get in set metodami bolji od uporabe javnih spremenljivk. Spotoma pa
bomo navedli e kak razlog in (upamo) prepriali e zadnje dvomljvce, ki se tako teko poslovijo od javnih
spremenljivk.
Razlogi, zakaj je dostop do podatkov v objektu preko metod bolji kot neposredni dostop (preko javnih
spremenljivk) so med drugim:
Monost kontrole pravilnosti!
Monost kasneje spremembe naina predstavitve (hranjenja podatkov).
Monost oblikovanja pogleda na podatke:
Podatke uporabniku posredujemo drugae, kot jih hranimo. Tako denimo v razredu Datum mesec
hranimo kot tevilo, proti uporabniku pa je zadeva videti, kot bi uporabljali besedni opis meseca.
Dostop do doloenih lastnosti lahko omejimo:
Npr. spol lahko nastavimo le, ko naredimo objekt (kasneje pa uporabnik spola sploh ne more
spremeniti, saj se ne spreminja ... e odmislimo kakne operacije, doloene vrste ivali ... seveda)
Hranimo lahko tudi doloene podatke, ki jih uporabnik sploh ne potrebuje ..
Nastavitve podatkov (stanj)
Potrebujemo torej metode, ki bodo nadomestile prireditveni stavek. Za tiste podatke, za katere elimo, da jih
uporabnik spreminja, napiemo ustrezno set metodo. Na primer:
zajcek.SpremeniTezo(2.5);
V bistvu smo s tem dosegli isto kot prej s prireditvenim stavkom
zajcek.masa = 2.5;
A metoda spremeniTezo lahko PREVERI, e je taka sprememba tee smiselna! Tako je zapis
zajcek.SpremeniTezo(-12.5);
naeloma nadomestek stavka
zajcek.masa = -12.5;
Vendar gre tu za bistveno razliko. Prireditveni stavek se bo zagotovo izvedel (in bo s tem zajec nevarno shujal).
Pri spreminjanju tee zajca z metodo, pa lahko prepreimo postavitev lastnosti objekta v napano stanje! V
metodi SpremeniTezo lahko izvedemo ustrezne kontrole in e sprememba ni smislena, je sploh ne izvedemo.
Mimogrede, e bi li v podrobnosti jezika C#, bi videli, da lahko doloene komponente proglasimo za lastnosti
(Property), ki zahtevajo, da jim napiemo metodi z imenom get in set in potem lahko uporabljamo notacijo
imeObjekta.imeLastnosti. Na zunaj je videti, kot bi imeli javne spremenljivke. V resnici pa je to le "zamaskiran"
klic get oziroma set metode. Mi bomo lastnosti spustili in bomo pisali "svoje" get in set metode.
Programiranje 1 VS Informatika
C# . NET
447:
448:
449: }
50
Ali imamo lahko obe metodi? al ne, saj imata obe enak podpis. Spomnimo se, da podpis sestavljajo ime
metode in tipi parametrov. Tip rezultata pa ni del podpisa! Pri sestavljanju razreda se bomo torej odloili za eno
teh dveh metod (odvisno od ocenjenih potreb).
Metoda je seveda lahko bolj kompleksna. Denimo da vemo, da se tea zajca med dvema tehtanjima ne more
spremeniti bolj kot za 15%. Zato lahko z metodo "polovimo" morda napane poskuse sprememb.
R A Z R E D Z A J E C S P R E M E N I T E Z O VM E J A H
450: public bool SpremeniTezoVmejah(double novaTeza) {
451:
// smislena nova teza je le med 0 in 10 kg
452:
// in e ni ve kot 15% spremembe od zadnji
453:
int sprememba = (int)(0.5 + (100 *
454:
Math.Abs(this.masa novaTeza) / this.masa);
455:
456:
if ((0 < novaTeza) && (novaTeza <= 10) && (sprememba <= 15) ){
457:
masa = novaTeza; // this.masa ... Lahko pa this spustimo!
458:
return true; // sprememba uspela
}
459:
460:
// v nasprotnem primeru NE spremenimo tee
// in javimo, da spremembe nismo naredili
461:
462:
return false;
463: }
Kaj pa metodi za spreminjanje serijske tevilke in spola? Na zadnjo lahko mirno pozabimo. Zajec naj ima ves as
tak spol, kot mu ga doloimo pri "stvarjenju" (torej v konstruktorju). Zato set metode za spremninjanje spola
sploh ne bomo napisali. In ker je spremenljivka spol zaitena s private, je uporabnik ne bo mogel spremeniti.
Seveda, e bomo na razred Zajec potrebovali za kaken genetski laboratorij, kjer se gredo udne stvari, pa bo
morda metoda SpremeniSpol potrebna.
Tudi serijske tevilke verjetno ne bomo spreminjali. No, e malo bolje premislimo, pa nam konstruktor brez
parametrov ustvari zajca, ki ima za vrednost serijske tevilke niz "NEDOLOENO". Takim zajcem bomo verjetno
eleli spremniti serijsko tevilko. Zato naj metoda SpremeniSerijsko pusti spreminjati le nedoloene serijske
tevilke!
S PREDPONO
C# . NET
51
NA
0.5 K G
NATANNO
Programiranje 1 VS Informatika
C# . NET
52
"april",
Seveda so potrebne e spremembe v drugim metodah. Npr. uporabnik bo verjetno elel imeti metodi
NastaviMesec, ki bosta sprejeli bodisi tevilni ali pa opisni podatek.
Ostale metode
Poleg get/set metod in konstruktorjev v razredu napiemo tudi druge metode, saj objektov ne potrebujemo
samo kot "hranilnikov" podatkov. S temi metodami doloimo
odzive objektov
"znanje objektov"
e se na primer spomnimo na objekte tipa string:
Znajo povedati, kje se v njih zane nek podniz:
"niz".IndexOf("i")
o
o
nekNiz.toLower()
mojPriimek.Equals("Lokar")
Zato bomo tudi v "naih" razredih sprogramirali znanje objektov doloenega razreda s tem, da bomo napisali
ustrezne metode. Katere bodo te metode je pa odvisno od nartovane uporabe naih razredov.
Kot enostaven zgled recimo, da bo zajec znal povedati svojo vrednost, e mu povemo ceno za kg ive tee.
"Komercialno" zanimiva bi bila e metoda, ki bi vrnila true, e je smiselno zajca tik pred tehtanjem (in prodajo)
poteno napojiti.Spomnimo se namre, da teo zajcev uporabnikom povemo na pol kg natanno, eoprav jo
interno hranimo tono.
RAZRED ZAJEC
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
DODATNE METODE
Metoda ToString
Poglejmo si naslednji program:
Programiranje 1 VS Informatika
C# . NET
IZPIS
53
OBJEKTA
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);
}
}
}
e ga izvedemo, na zaslon dobimo
METODA TOSTRING
public override string ToString()
{
return "Zajec: " + this.PovejSerijsko();
}
Programiranje 1 VS Informatika
C# . NET
54
Opazimo novo neznano besedo override. Uporabiti jo moramo zaradi "dedovanja". Ve o tem, kaj
dedovanje je, kasneje, a povejmo, da smo z dedovanjem avtomatino pridobili metodo ToString. To je
razlog, da je ta metoda vedno na voljo v vsakem razredu, tudi e je ne napiemo.
e elimo napisati svojo metodo, ki se imenuje enako kot podedovana metoda, moramo napisati besedico
override. S tem "povozimo " podedovano metodo.
Seveda bi lahko napisali tudi neko drugo metodo, na primer Opis, ki bi prav tako vrnila niz s smiselnim opisom
objekta.
Razlika med
METODA TOSTRING
public override string ToString()
{
return "Zajec: " + this.PovejSerijsko() ;
}
in
METODA OPIS
public string Opis()
{
return "Zajec: " + this.PovejSerijsko() ;
}
je v tem, da moramo metodo Opis poklicati sami, metoda ToString pa se klie avtomatsko (e je potrebno).
e torej napiemo
CELOTNI
RAZRED
ZAJEC
C# . NET
480:
481:
482:
483:
484:
485:
486:
487:
488:
489:
490:
491:
492:
493:
494:
495:
496:
497:
498:
499:
500:
501:
502:
503:
504:
505:
506:
507:
508:
509:
510:
511:
512:
513:
514:
515:
516:
517:
518:
519:
520:
521:
522:
523:
524:
525:
526:
527:
528:
529:
530:
531:
532:
533:
55
this.serijska = "NEDOLOENO";
}
public Zajec (string serijskaStev) {
this(); // poklicali smo konstruktor Zajec()
this.serijska = serijskaStev;
}
public Zajec(string serijskaStev, bool spol, double masa) {
this(); // poklicali smo konstruktor Zajec()
this.serijska = serijskaStev;
this.SpremeniTezo(masa); // uporabimo metodo za sprem.
this.spol = spol;
}
public double PovejTezo() {
// teo bomo povedali le na 0.5 kg natanno
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;
return true; // sprememba uspela
}
// v nasprotnem primeru NE spremenimo tee
// in javimo, da spremembe nismo naredili
return false;
}
public string PovejSerijsko() {
return this.serijska;
}
public bool SpremeniSerijsko(string seStev) {
// sprememba dopustna le, e serijske tev. ni
if (this.serijska.Equals("NEDLOENO")) {
this.serijska = seStev;
return true;
}
return false; // ne smemo spremniti e obstojee!
}
public bool JeSamec() {
return this.spol;
}
// ker se spol naknadno NE spremeni, metode za
// spreminjanje spola sploh ne ponudimo uporabniku!
public double Vrednost(double cenaZaKg) {
Programiranje 1 VS Informatika
C# . NET
534:
535:
536:
537:
538:
539:
540:
541:
542:
543:
544:
545:
546:
547:
548:
549:
550:
551:
56
UPORABA
STAREGA RAZREDA
ZAJEC
UPORABA
NOVEGA RAZREDA
ZAJEC
C# . NET
57
Programiranje 1 VS Informatika
C# . NET
58
class
gre za to, da zaeno pisati nart objekta, ablono po kateri bomo ustvarjali objekte. Z ustvarjanjem razredov si
pripravljamo sestavne dele, s pomojo katerih bomo reevali nek problem.
Ko pa sestavljamo program, ki predstavlja algoritem, s katerim reujemo problem, pa na podlagi teh
pripravljenih nartov (razredov) ustvarimo primerek razreda konkretni objekt. Pogosto bomo prebrali, da je
objekt instanca nekega razreda, a to je nepotrebno "paenje" slovenskega jezika. Za besedo instanca obstaja
isto lep slovenski izraz primerek.
Primerek razreda (konkretni objekt) ustvarimo ga z new. Dokler new ne uporabimo, objekta ni in ga seveda ne
moremo uporabiti. e torej napiemo
NekiObjekt a;
Ne pozabimo, da objekt s tem e ne obstaja. Spremenljivka a je samo ime objekta, oziroma natanneje , a je
ime spremenljivke, kjer bomo hranili naslov objekta vrste NekiObjekt. ele new bo naredil objekt in vrnil
naslov, kje ta objekt je. In ta naslov bomo shranili v a.
Problem Banke Butale
Banka Butale se intenzivno pripravlja na prihod nove valute arve. Med drugim bo potrebno nakovati nove
kovance. Za ustrezno informacijsko podporo kovanici najamejo tebe. Po nekajmesenih pogovorih ugotovi,
da bomo v programih potrebovali objekte vrste Kovanec.
Potrebujemo torej razred Kovanec. Kaj pa sedaj?
Kako do svojega razreda
Najlaje je, e ustrezen razred e obstaja v standardnih knjinicah jezika C#. e ga tam ni, se splaa pogledati
okoli. Morda je kdo drug pripravil knjinico, v kateri je iskani razred. Kaj pa, e na triu ni niti priblino
ustreznega razreda.
Takrat moramo narediti razred sami. Kako se tega lotimo?
Skica postopka z opombami bi bila:
o Analiza:
Pa ne matematini predmet
Katera so stanja/lastnosti:
Kaj hoemo o objektih te vrste vedeti
Kakne lastnosti imajo
Katere so metode:
Kakno je znanje objektov
Na katere ukaze se odzovejo
o Predstavitev razreda (priprava class)
Pisanje metod
o Preverjanje delovanja posameznih metod
Programiranje 1 VS Informatika
C# . NET
59
Ko smo z analizo konali, se lotimo pisanja razreda. Pa tudi tu e ne pride takoj na vrsto kodiranje. Anjprej se
moramo odloiti, kako bomo eljene podatke hranili. Kakne bodo spremenljivke (kaknega tipa), koliko jih bo
... Praviloma vse spremenljivke, v akterih hranimo podatke o objektu, "skrijemo". Za zunanje uporabnike jih
napravimo nevidne z doloilom private.
Ko smo se odloili o nainu predstavitve lastnosti, se lotimo pisanja ustreznih metod. Ko smo konali, dobro
preverimo delovanje vseh metod. Na koncu, a kot zelo pomembno zadevo, pa pripravimo e dokumentacijo o
razredu, kjer tono opiemo parametre vseh metod, tip rezultata ter namen posamezne metode. Pri pisanju
komentrajev soi pomagamo z orodji, ki to dokumentacijo avtomatino ustvarijo na podlagi dokumentacijskih
komentarjev.
Okostje razreda
Oglejmo si, kako bo videti tipini razred, ki ga bomo sestavljali.
Vrstni red sicer ni pomemben, a se najvekrat drimo prav takega. Pohosto sicer vidimo, da je v razredu tudi
metoda Main, ki jo uporabljamo za preverjanje delovanja razreda. A naeloma to ni najbolje, kar "zamegljuje"
sliko. Razred naj bo pa nart za objekte nekega tipa. V drugem programu (ki pa je tudi razred, a brez
komponent, objektnih metod ...) pa pa objekte pripravljenih razredov uporabljamo.
public class Razred {
// deklaracija lastnosti - komponent - polj - ...
// konstruktorji
// metode
// ToString
}
Razred Kovanec
Sestavimo sedaj razred Kovanec, s katerim predstavimo kovance v obliki, kot jih bomo potrebovali za butalsko
banko..
Naredimo analizo:
KOVANEC -
SKICA
C# . NET
230:
231:
232:
233:
234:
niz
235:
236:
237:
238:
239:
240: }
60
KOVANEC
DEL METOD
Programiranje 1 VS Informatika
C# . NET
61
Pri metodi NastaviPolmer pa zgolj vrednost parametra zapiemo v spremenljivko in s tem spremenimo lastnost
objekta. Torej neprevidni programer lahko "naredi kovanec" z negativnim polmerom. Vsekakor pri "pravem
2
programiranju" metode ne bomo napisali na ta nain.
Pri metodi za opis objektov vrste kovanec smo se odloili, da je smielen opis objekta dvovrstini. V prvi vrstici
pie r xx, v drugi pa visina xxx, kjer je namesto xx seveda ustrezna vrednost.Opazimo tudi, da do vrednosti
polmera dostopamo preko metod. To sicer ni potrebno in bi metodo lahko napisali tudi kot
METODA TOSTRING
1:
2:
3:
4:
Z NEPOSREDNIM DOSTOPOM
Torej z neposrednim dostopom do spremenljivk. To lahko naredimo, saj smo znotraj razreda. A je vseeno
bolje, e metodo napiemo na prej predstavljeni nain. Vemo, da se Butalci pogosto radi malo postavijo
nasproti Verejcem. In ker se Verejci hvalijo, da so njihovi kovanci precej veji, jim Butalci ne bodo ostali
dolni. Po e-poti dobi zahtevo, da "popravi" razred Kovanec tako, da bo javljal 2x veji polmer (podatek o
polmeru naj bo v objektu za vsak primer zapisan kar pravi, le navzven naj se "pretvarja" da je dvakrat veji) . In
e smo dostop do lastnosti polmer povsod izvajali preko metode PovejPolmer() ustrezno spremembo
napravimo le na enem mestu.
Uporaba razreda Kovanec
Prvi problem, ki ga mora reiti za butalsko banko, je problem njihove dravne kovnice. Dravna kovnica eli, da
napie program, ki rei naslednji problem. Kovino za izdelovanje kovancev imajo v kovnici obliki enega samega
velikega kvadra z merami 20 x 12 x 30 (za ve ni prostora, saj je arhitekt, ko (ki je povsem sluajno isti kot
arhitekt neke fakultete) je risal narte za kovnico pozabil na skladie. Ko Banka Butale potrebuje nekaj
kovancev, jih zanima, e bodo iz tega kvadra res lahko izdelali eljeno tevilo kovancev. Zato bi radi imeli
program,m ki pove, ali lahko naredimo n "obiajnih" kovancev (torej takih, kot jih naredi konstruktor
Kovanec()).
Problem sploh ni lahek. A e ga "razumemo prav" in upotevamo da lahko kvader potem tudi malo
preoblikujemo, odpadke spet zlijemo skupaj in ponovno kujemo, ... Poleg tega moram,o odgovore programa
(DA/NE) pravilno tolmaiti.
ne: nikakor to ne gre
da: mogoe, ni pa nujno
Program bo enostaven. Z new Kovanec() ustvarimo nov, obiajni kovanec. Povpraajmo ga, koliko je njegov
volumen. e n kratnik volumna presega volumen kvadra, vemo, da s kovanjem taknega tevila kovancev ne bo
ni in dogovorimo NE. V nasprotnem pa ostaja upanje, da bodo vrli butalski kovai e nekako nakovali n
kovancev in odgovorimo DA.
UPORABA
RAZREDA
KOVANEC
C# . NET
289:
290: }
62
Program je napisan, v Butalah so nad njim navduzeni. A ne mine leto, ko dravni zakladnik spremeni dimenzije
"obiajnih" kovancev. Je potrebno spremeniti program? Kje so potrebne spremembe?
Spremembe v programu niso potrebne. Popraviti je potrebno seveda razred Kovanec, kjer spremenimo
delovanje konstruktorja brez parametrov. A to je vse. V uporabnike programe, torej tiste, ki razred Kovanec
uporabljajo, se ni potrebno vtikati!
Razrede sestavljamo tako, da uporabniki tega razreda niso prizadeti ob morebitnih spremembah razredov
Komponente
ToString
Kvader podatki
Kvader kot geometrijsko telo je podan z dolinami vseh treh stranci. Odloiti se moramo torej kako bo imel
objekt predstavljene stranice. Ena od monosti je, da uporabimo 3 spremenljivke tipa int. Druga monost bi
bila, da vzamemo tabelo s tremi polji. Spet tretja, da podatke predstavimo kot niz oblike "a x b x c". Spet etrta
monost ...
V naem zgledu se bomo odloili kar za prvo monost. Uporabili bomo torej
Vsi programi, ki uporabljajo objekte doloenega razreda, si podatke izmenjujejo le preko metod
Programiranje 1 VS Informatika
C# . NET
63
PovejA(),
Za podatke, za katere je smiselno, da jih uporabnik spremeni, pa pripravimo metode, ki spremenijo vrednost
podatka. Ob tem obiajno preverimo, e je podatek smiselen. Kaj pa naredimo, e podatek ni smsielene, je
odvisno od namena, za katerega sestavljamo razred. Tako se na primer lahko odloimo, da podatka enostavno
ne spremenimo in morda to javimo, preko izhodnega rezultata tipa int ali bool. Lahko v primeru napanih
podatkov privzamemo, da potem podatek objekta spremenimo na neko vnaprej doloeno vrdnost ... Vse te
odloitve (kaj storimo ob napanih podatkih) pa dobro dokumentiramo v dokumentaciji. Tako bodo uporabniki
tega razreda vedeli, kaj lahko priakujejo. . V naem razredu bomo napisali metode oblike
StranicaA(),
Kvader konstruktorji
K metodam, ki spreminjajo podatke, na doloen nain spadajo tudi konstruktorji. Z njimi najpogosteje
nastavimo zaetne vrednosti podatkov v objektu. Pri tem ne smemo pozabiti, da mora tudi konstruktor
poskrbeti, da bodo shranjeni podatki smiselni. e posebej pa moramo biti pazljivi na to, da objekt ob klicu
3
konstruktorja e nima nastavljenih smiselnih podatkov . Zato si obiajno ne privoimo tega, da bi v primeru
napanih poarametrov v konstruktorju ne naredili ni, amapak zamenjamo napane vrednosti parametrov z
nekeimi, vnaprej dogopvorjenimi (in v dokumentaciji dobro opisanimi) vrednostmi.
e pri razlagi uporabe konstruktorjev smo omenili, da skoraj vedno pripravimo konstruktor brez parametrov.
Tak konstruktor naredi privzeti objekt. Denimo, da je na privzeti objekt kvader s stranicami: 1 x 1 x 1.
Ustrezni konstruktor bo
KONSTRUKTOR
BREZ PARAMETROV
public Kvader(){
a = 1;
b = 1;
c = 1;
}
Naeloma ta konstruktor zadostuje. e elimo narediti drugaen kvader, pa naredimo osnovni kvader in mu z
ustreznimi metodami spremenimo stranice. Kaj pa, e bi uporabniku radi ponudili ve monosti zaetnega
kvadra? Denimo
Konstruktor, ki naredi kocko
Navedimo sedaj kar celoten razred. V njem smo napisali cel kup komentarjec, doloene zadeve smo po
nepotrebnem pisali drugae, le zato, da smo lahko pripraili ustrezne komentarje. Sem in tja bomo kodo prekinili
z razlago. Opazili boste, da smo namenoma malo premeali vrstni red. Na ta nain elimo opozoriti, da je vrstni
red metod v razredu povsem poljuben.
RAZRED
KVADER
Rsnici na ljubo imajo vse komponente, ki opisujejo objekt, takoj nastavljene privzete vrednosti. A do sedaj
smo se e nauili, da se zanaanje na to, da bo za nekaj poskrbel prevajalnik, obiajno ne kona najbolje.
Spomnimo se le teav, ki smo jih imeli, ker je prevajalnik sam namesto nas pripravil konstruktor brez
parametrov.Tudi tu je vpraanje, le privzete vrednosti opisujejo "legalno" stanje objekta.
Programiranje 1 VS Informatika
C# . NET
295:
296:
297:
298:
299:
300:
301:
302:
303:
64
e pred spremenljivko ob deklaraciji napiemo const, s tem povemo, da gre za konstanto. To pomeni, da
vrednosti, ki jo priredimo ob deklaraciji, potem ne moremo ve spreminjati. Tudi konstante so lahko javne ali
privatne. Lahko jih piemo lokalno (znotraj metod), lahko pa reemo, da so to lastnost razreda (in jih napiemo
izven vseh metod, tja kot objektne spremenljivke. Navada je, da jih poimenujemo z imenom, ki vsebuje same
velike rke. Pogosto jim doloimo javni dostop, saj jih uporabnik tako ali tako ne more spreminjati, saj so
konstante. Seveda pa, e bi jih uporabniku radi predstavili drugae (prego get metod) ali jih pred njim skrili,
lahko uporabimo private.
Gre za tako imenovane razredne (statine) podatke . To pomeni, da obstajajo neodvisno od obstioja kaknega
primerka in da do njih dostopamo (e so public) z
ImeRazreda.IME_KONSTANTE
Ve o tem v razdelku, ko bomo na dolgo govorili o statinih (razrednih) podatkih.
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
Tu smo napisali pomono metodo, ki preveri, e je podatek v mejah, kot jih doloata konstanti. Ker smo ocenili,
da metoda za uporabnika ni uporabna, smo jo s private pred njim skrili. Tako je ne more uporavljati in je na
voljo izkljuno znotraj tega razreda.
331:
332:
// nastavi podatek
Programiranje 1 VS Informatika
C# . NET
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359:
360:
361:
362:
363:
364:
365:
366:
367:
368:
369:
370:
65
Tu smo spet enkrat za spremembo uporabili kombinacijo prireditvenega stavka in prireditvenega izraza. e se
spomnimo iz poglavja o datotekah, kjer smo tudi naleteli na prireditveni izraz, je to izraz, ki ima poleg tega, da
vrne vrednost, e stranski uinek. Ta je, da spremenjlivko nastavi na to vrednost, ki jo sicer vrne kot vrednost
izraza.
Konkretno vrstica 79 vse tri stranice nastavi na 1.
371:
372:
373:
374:
375:
376:
Tu vidimo, da smo namesto napane vrednosti kar sami doloili ustrezni podatek (1). Neklaj takega moramo
storiti, saj konstruktor mora nastaviti podatke o objektu na neke smiselne vrednosti (in jih ne moremo kar
pustiti nenastavljen oziroma upati, da so privzete vrednosti v jeziku C# ustrezne za na razred).
377:
C# . NET
378:
379:
380:
381:
382:
383:
384:
385:
386:
387:
388:
389:
390:
391:
392:
393:
394:
395:
396:
397:
398:
399:
400:
401:
66
Morda se spraujete, kje je tukaj new. Ko smo v enem od prejnjih zgledov sestavljali metodo, ki vrne kopijo
objekta, smo e posebej poudarili, da ne smemo pozabiti na new znotraj metode. A ne pozabimo, da smo v
konstruktorju. Torej se je objekt ravnokar naredi (prav z new) in mi le nastavljamo njegove podatke.
402:
//
403:
404:
// --------------- to string
405:
//
406:
override public String ToString(){ /* prekrivanje metode iz razreda
Object */
407:
408:
// Metoda vrne podatek v obliki Kvader: a x b x c
409:
return "Kvader: " + PovejA() + " x " + PovejB() + " x "
410:
+ PovejC();
411:
/* tudi znotraj razreda se splaca uporabljati metode za
412:
delo s podatki
413:
ceprav imamo neposreden dostop do spremenljivk, saj
nam ob morebitni
414:
415:
spremembi predstavitve ni potrebno toliko popravljati! */
416:
}
417: } // class Kvader
Ustvarjanje razredov in objektov: povzetek
Nredimo sedaj povzetek vsega povedanega.
Konkretni objekt je primerek nekega razreda . Nastane z new. Izjema so na prvi pogled objekti razreda string. A
dejansko ne gre za izjemo, gre le drugaen zapis, ki "skrije" uporabo operatiorja new! Podobno je pri tabelah ko
uporabimo inicializacijo zaetnih vrednosti, naptetih v zavitih oklepajih.
Posaminim lastnostim objekta vedno doloimo privatni nain dostopa (da so torej dostopni le metodam
znotraj razreda). To povemo tako, da ob deklaraciji napiemo private. Razlog za to je v tem, da uporabnika ne
zanima nain hranjenja lastnosti objekta, ampak le smiselna uporaba objektov. S tem tudi omogoimo tudi bolj
kontrolirano delo s podatki v objektu. V ta namen pripravimo metode za delo s podatki/lastnosti kot so :
VrniPodatek, NastaviPodatek
Programiranje 1 VS Informatika
C# . NET
67
V razredu moramo obvezno imet tudi konstruktorje. To so metode, ki povedo, kaj se zgodi ob kreaciji novega
objekta. Prvenstveno podskrbijo, da so vsi podatki o objektu takoj nastavljeni na smislene vrednosti.
Ko piemo metode, s katerimi nastavljamo vrednost (set), ne smemo pozabiti na preverjanje pravilnosti
parametrov, Stanje objekta mora biti ves as pravilno. Ne smemo pozabiti na ustreno preverjanje parametrov
e pri pisanju konstruktorjev. Kot smo omenili, morajo tudi ti poskrbeti, da je novoustvarjeni objek v
"smiselenem stanju")
Pri metodah, s katerimi vraamo vrednost (t.i. get metode, vejih zapletov ne gre priakovati. Seveda pa lahko
metode izkoristimo, da podatke, ki jih v objektu hranimo na en nain, vrnemo na drug nain,.
Vsak na razred naj bi imel tudi metodo ToString. Ta poskrbi, da se bodisi ob klicu, bodisi avtomatino (e se na
tistem mestu namesto objekta priakuje niz) objekt pretvori v niz. Uporabljamo jo za predstavitev objekta.
Ker zaradi mehanizma dedovanja ta metoda avtomatino obstaja v vsakem razredu, moramo na zaetek dodati
e besedo override,
Poleg metod za nastavljanje/vraanje podatkov in metode ToString imamo v razredu obiajno e ve drugih
metod. Tiste, katerih uporaba je namenjena uporabnikom, se zano z doloilom public, interne (pomone)
metode pa s private.
Predvsem ori konstruktorjih smo uporabili tehniko preobteevanja (overloading). Gre za to, da imamo lahko
ve metod, ki se imenujeo enako, razlikjejo pa se v seznamu parametrov.
Zgledi
Ogledali si bomo nekaj postopkov pri katerih uporabimo objektno programiranje.
Avto
Izdelujemo spletno anketo o priljubljenosti razlinih avtomobilov. V ta namen bomo sestavili razred Avto, ki naj
hrani tri osnovne podatke o velikosti (dolini), barvi in o tipu (limuzina ali kupe):
velikost (dolino): decimalno tevilo med 4.0 in 5.0,
barvo: poljuben niz in
ali je avto tip limuzine ali kupeja.
Vse spremenljivke razreda morajo biti privatne, razred pa mora tudi poznati metode za nastavljanje in branje
teh vrednosti. Metoda za nastavljanje velikosti avta naj poskrbi tudi za to, da bo velikost vedno ostala znotraj
sprejemljivih meja! e uporabnik poskusi doloiti napano velikost, naj se obdri prejnja vrednost.
Mona reitev:
RAZRED AVTO
public class Avto
{
private double velikost;
private string barva;
private bool tip; // true pomeni, da gre za limuzino,
// false, da je kupe
// konstruktor
public Avto()
{
this.tip = true; // vsem privzetim avtom na zaetku
// doloim tip limuzine
this.velikost = 4.0; // in so 4 m veliki
this.barva = "nedoloena";
}
public Avto(string barvaKatera, bool tip, double velikost)
{
this.barva = barvaKatera;
this.tip = tip;
Programiranje 1 VS Informatika
C# . NET
68
if (!this.SpremeniVelikost(velikost))
//e metoda spremeni velikost ni uspela
//moramo "rono" nastaviti velikost
this.velikost = 4.0;
}
public double PovejVelikost ()
{
// velikost bomo povedali le na 0.5 metra natanno
int velikostMetri = (int) this.velikost;
int decim = (int) ((this.velikost - velikostMetri)*10);
if (decim < 4) return velikostMetri + 0.0;
if (decim < 5) return velikostMetri + 0.5;
return velikostMetri + 4.0;
}
public bool SpremeniVelikost (double novaVelikost)
{
//smiselna nova velikost je le med 4 in 5 metri
if ((4 < novaVelikost) && (novaVelikost <= 5))
{
this.velikost = novaVelikost;
return true; // sprememba je uspela
}
// v nasprotnem primeru ne spremenimo velikosti in
// javimo, da spremembe nismo naredili
return false;
}
public string PovejBarvo ()
{
return this.barva;
}
public void SpremeniBarvo (string b)
{
this.barva = b;
}
public bool JeLimuzina ()
{
return this.tip;
}
public string KaksenTip ()
{
if (this.JeLimuzina()) return "limuzina";
return "kupe";
}
// ker se tip avta naknadno ne spremeni,
// metode za spreminjanje tipa sploh ne ponudimo uporabniku!
// metoda ToString
Programiranje 1 VS Informatika
C# . NET
69
a1.SpremeniVelikost(a1.PovejVelikost() + 0.3);
vrstica 7 pa
a1.SpremeniVelikost(a1.PovejVelikost() + 0.3);
bo njegova dejanska velikost 4.8m, eprav bo metoda PovejVelikost() sporoala, da je dolg 5m.
Denarnica
C# . NET
70
Napii metode get in set. V set metodi za evre in cente preveri smiselnost podatka - e je
koliina denarja, ki naj bo v denarnici, manja od 0, naj se vrednost komponente ne spremeni.
Napii tudi metodo ToString, ki vrne niz V denarnici, katere lastnik je #ime_lastnika je
#st_evrov evrov in #st_centov centov.
Napii program, ki ustvari tabelo desetih denarnic z nakljuno mnogo denarja. S pomojo metode izpii to
tabelo.
Reitev:
C# . NET
71
C# . NET
72
Vaje
Zival
RAZREDA
ZIVAL:
C# . NET
73
*/
public Zival() {
steviloNog = 4;
vrsta = "pes";
ime = "Pika";
}
// Vrne ime zivali.
public string VrniIme() {
return this.ime;
}
// Vrne vrsto zivali.
public string VrniVrsto() {
return this.vrsta;
}
/* Vrne stevilo nog zivali.
Zagotovljeno je, da bo stevilo nog vedno vecje od 0.
*/
public int VrniSteviloNog() {
return this.steviloNog;
}
/*Nastavi ime zivali.*/
public void NastaviIme(string vrednost) {
if(vrednost != null) {
this.ime = vrednost;
}
}
/*Nastavi vrsto zivali.*/
public void NastaviVrsto(string vrednost) {
if(vrednost != null) {
this.vrsta = vrednost;
}
}
/*Nastavi stevilo nog zivali.*/
public void NastaviSteviloNog(int vrednost) {
if(vrednost > 0) {
this.steviloNog = vrednost;
}
}
}
Naloga:
Dopolnite razred z metodo override public String ToString(), ki naj izpie podatke o
objektih v obliki: #Ime: je vrste #vrsta in ima #steviloNog nog. Pri tem seveda
zamenjajte #vrsta in #steviloNog z vrednostmi v istoimenskih spremenljivkah.
Nato napiite testni program, kjer ustvarite 5 ivali in jim nastavite smiselno vrsto in imena
ter tevilo nog. Izpiite jih!
Programiranje 1 VS Informatika
C# . NET
74
Razred Kolega
Sestavi razred Kolega, ki ima tri komponente:
ime
priimek
telefonska tevilka
Vse tri komponente naj bodo tipa string in javno dostopne.
Napii vsaj dva konstruktorja:
prazen konstruktor, ki vse tri komponente nastavi na "NI PODATKOV".
konstruktor, ki sprejme vse tri podatke in ustrezno nast avi komponente
Napii tudi metodo public string ToString(), ki vrne niz s smiselnim izpisom podatkov o
objektu tipa Kolega (ime, priimek in telefonska tevilka).
Preizkus razreda Kolega
Sestavi testni program, v katerem ustvari dva objekta tipa Kolega. En objekt ustvari s praznim
konstruktorjem, drugega s konstruktorjem, ki sprejme tri parametre. Oba objekta tudi izpii na zaslon.
Uporaba razreda Kolega
Napii program, ki sestavi tabelo 10ih objektov tipa Kolega, prebere telefonsko tevilko in izpie tiste objekte iz
tabele, ki imajo tako telefonsko tevilko. e takega objekta v tabeli ni, naj se izpie: "Noben moj kolega nima
take telefonske tevilke."
Naloge brez raunalnika
Sledee naloge reuj brez uporabe raunalnika!
1.
KODA
Z NAPAKO
Dana je koda:
C# . NET
b.
c.
d.
e.
f.
3.
y2
y3
y4
y5
y6
=
=
=
=
=
new
new
new
new
new
75
Y(2);
Y;
Y();
Y(10.0, 3);
Y[5];
Dana je koda
588:
589:
C# . NET
590:
591:
592:
593:
594:
595:
596:
597:
76
int a = 5;
int[] b = {5};
inc.Povecaj (a);
inc.Povecaj (b);
Console.WriteLine("a = " + a);
Console.WriteLine("b = " + b[0]);
Datum
Sestavi razred Datum, ki predstavlja datum (dan, mesec in leto). Definiraj ustrezne komponente in
konstruktorje.
Definiraj metodo override public string ToString(), ki vrne datum predstavljen z nizom
znakov.
Definiraj metodo public bool Equals(Datum d), ki vrne True, e je datum this enak
datumu d.
Datum 2
Razredu Datum dodaj metodo public
ter vrne celo tevilo:
< 0, e je this pred d
0, e je this enak d
> 0, e je this za d
Oseba
Oseba 1
Sestavi razred Oseba, ki vsebuje podatke o osebi, in sicer:
ime
priimek
datum rojstva
Za predstavitev datuma uporabi razred Datum iz prejnje naloge.
Definiraj ustrezne konstruktorje in metodo public string
nizom znakov.
Razred preizkusi tako, da naredi osebo, ki predstavlja tebe.
Oseba 2
Razredu Oseba dodaj metodo public
pravi ime in priimek, loena s presledkom.
Oseba in datoteke
Razredu Oseba dodaj metodi public void Shrani(StreamWriter ime) in
konstruktor public Oseba(StreamReader ime) za zapisovanje in branje osebe z datoteke.
Metoda shrani(w) zapie na w v eno vrstico podatke o osebi v obliki, ki je primerna za branje, na primer
nekaj takega kot
Miha:Novak:23:7:1982
Konstruktor Oseba(r) prebere z r eno vrstico, ki je bila predhodno zapisana s Shrani, in zapie
podatke v komponente objekta this.
Preveri, ali metoda in konstruktor pravilno delujeta.
Programiranje 1 VS Informatika
C# . NET
77
Oseba in datoteke 2
Razredu Oseba dodaj statini metodi public
static void
ShraniSpisek(Oseba[] spisek, string dat) in public Oseba[]
static NaloziSpisek(string dat), ki shranita in naloita tabelo oseb na datoteko z
imenom dat.
Preveri, ali metodi pravilno delujeta. V pomo naj ti bo spisek naslednjih oseb:
osebe.dat
Miha:Novak:23:7:1982
Josip:Broz:7:5:1892
Josip:Plemelj:11:12:1873
Britney:Spears:12:2:1981
Kurt:Goedel:28:4:1906
Alan:Turing:23:6:1912
Leonhard:Euler:15:4:1707
Carl Friedrich:Gauss:30:4:1777
Oseba in datoteke 3
Napii statino metodo public static void rojeni_pred(string dat,
Datum d), ki iz datoteke z imenom dat prebere spisek oseb in na zaslon izpie tiste osebe, ki so rojene
pred datumom d.
Preveri, ali metoda pravilno deluje.
Majica
Sestavite razred Majica, ki hrani osnovne podatke o majici:
o velikost: tevilo med 1 in 5,
o barvo: poljuben niz in
o ali ima majica kratke ali dolge rokave.
Vse spremenljivke razreda morajo biti privatne, razred pa mora tudi poznati metode za
nastavljanje in branje teh vrednosti. Podpisi teh metod naj bodo:
o public int VrniVelikost() ter public void SpremeniVelikost(int
velikost)
o public string VrniBarvo() ter public void SpremeniBarvo(string
barva)
o public boolean ImaKratkeRokave() ter public void
NastaviKratkeRokave(boolean imaKratkeRokave)
Metoda za nastavljanje velikosti majice naj poskrbi tudi za to, da bo velikost vedno ostala znotraj
sprejemljivih meja! e uporabnik poskusi doloiti napano velikost, naj se obdri prejnja vrednost.
Kandidat za direktorja banke
V banki je direktor uspel povzroiti politini kandal taknih razsenosti, da je moral odstopiti (seveda z
odpravnino v viini 50 povprenih pla) in zato sedaj isejo novega direktorja. Za to slubo se je prijavilo
kar nekaj kandidatov, od katerih je vsak predloil sledee podatke:
o ime
o priimek
o starost (v letih)
o stopnjo izobrazbe - tevilka med 3 in 8 (vkljuno)
Banka eli izbrati direktorja, ki ne bi bil stareji od 50 let (da bo lepo izgledal v medijih) in ima
vsaj 6. stopnjo izobrazbe. Tvoja naloga je:
sestaviti razred, ki bo hranil podatke o kandidatih za direktorja
dopolniti priloen testni program tako, da bo nael primerne kandidate za to mesto
in jih izpisal
Razred Kandidat mora poleg ustreznih spremenljivk (ki naj bodo privatne!) vsebovati vsaj
javne metode:
Programiranje 1 VS Informatika
C# . NET
78
o
o
o
o
public void NastaviImePriimek(string ime, string priimek) metoda, ki nastavi ime in priimek kandidata. e je sluajno ime oz. priimek enak null, naj
starega imena in priimka ne spremeni.
public string[] VrniImePriimek() - metoda, ki vrne ime in priimek kandidata.
Metoda naj vrne seznam nizov doline 2 - v prvem polju naj bo zapisano ime, v drugem
pa priimek kandidata.
public void NastaviStarost(int starost) - metoda, ki nastavi starost
kandidata. Starost mora biti v mejah med 20 in 80 let - e ni, naj se stara starost ne
spremeni.
public int VrniStarost() - metoda, ki vrne starost kandidata.
public void NastaviIzobrazbo(int izobrazba) - metoda, ki nastavi
izobrazbo kandidata. Izobrazba mora biti v mejah med 3 in 8 - e ni, naj se stara
izobrazba ne spremeni.
public int VrniIzobrazbo() - metoda, ki vrne izobrazbo kandidata.
598:
599:
600:
601:
602:
603:
604:
605:
606:
607:
608:
609:
610:
611:
612:
613:
614:
615:
616:
617:
618:
619:
620:
621:
622:
623:
624:
625:
626:
627:
628:
629:
630:
631:
C# . NET
79
632:
// tu poii najprimernejega kandidata in ga izpii
Console.WriteLine("Najprimernejsi
je:
633:
NajPrimernejsi(kandidati));
634:
635:
636:
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
637:
638:
}
639: }
"
Spremeni metodo NajPrimernejsi, tako, da vrne kandidata, ki je najmlaji in ima zahtevano stopnjo
izobrazbe (ali vijo).
Kandidat - najstareji
Recimo, da so si v banki premislili in bi radi namesto mladega neizkuenega direktorja zaposlili
najstarejega (ne glede na izobrazbo). Poii ga!
Denarnica
C# . NET
o
o
80
Podatkovni nosilec
Sestavite razred PodatkovniNosilec, ki predstavlja medij za shranjevanje podakov. Vsebuje naj
informacije o kapaciteti medija (celo tevilo, enota je bajt), izdelovalcu (niz ), osnovni ceni (celo tevilo,
enota je evroCent) in stopnji obdavitve (celo tevilo, enota je procent). Vsebovati mora vsaj javne
metode:
public PodatkovniNosilec() - konstruktor, ki ustvari nosilec kapacitete 650Mb, proizvajalca
"neznan", s ceno 100 centov in 20% davkom.
public PodatkovniNosilec(string ime, int kapaciteta, int cena, int davek) - konstruktor s
parametri.
public void NastaviKapaciteto(int bajti) - nastavi kapaciteto medija v bajtih. e je kapaciteta
negativna, naj se ne spremeni.
public void NastaviIme(string ime) - nastavi ime izdelovalca medija. e je ime enako null, naj
se ne spremeni.
public void NastaviCeno(int cena) - nastavi ceno. e je negativna, naj se ne spremeni.
public void NastaviObdavcitev(int pocent) - nastavi obdavitev v procentih. e so procenti
izven meja 0-100, naj se ne stara vrednost ne spremeni.
public int VrniOsnovnoCeno() - vrne osnovno ceno medija (brez davka).
public double VrniDavek() - koliko davka je potrebno plaati za ta medij (v evrih).
public double VrniProdajnoCeno() - vrne osnovno ceno + davek (v evrih).
public string VrniIme() - vrne ime proizvajalca medija.
public double VrniKapaciteto(char enota) - vrni kapaciteto v enoti, ki jo doloa znak enota:
o 'b' - bajti
o 'k' - kilobajti
o 'M' - megabajti
o 'G' - gigabajti
Pazi na to, da je en kilobajt 1024 (in ne 1000) bajtov!
public override string ToString() - vrne niz, ki smiselno opisuje razred.
Sestavi tudi testni program, v katerem preveri delovanje tvojega razreda.
Razred Zajec
Denimo, da piemo program, ki bo pomagal upravljati farmo zajcev.
Za vsakega zajca poznamo serijsko tevilko, spol in maso
Sestavi razred Zajec, ki vsebuje komponente:
spol //vrednost true, e je zajec mokega spola in false, e enskega (kaj hoete, moki
ovinisti ...)
masa //masa zajca v kilogramih (tip double)
serijska //serijska tevilka zajca (tip string)
Programiranje 1 VS Informatika
C# . NET
81
C# . NET
82
Popravi konstruktor in metodo za nastavljanje pozicije zajca tako, da ne bo dovolil vnosa napane lege
zajca (izven dovoljenga obmoja)!
Pri tem bodi pozoren na to, da mora pri branju lege zajca vrniti duplikat toke, saj bo drugae uporabnik
lahko v toko od zunaj vnesel napane podatke!
Mogoe se ti splaa napisati metodo public static Tocka Kopija(Tocka t) v razredu
Tocka, ki vrne kopijo toke t - torej novo toko na istih koordinatah.
Razdalja med dvema tokama
Ker velikokrat pride prav, da izraunamo razdaljo med dvema tokama, dopolni razred Tocka z metodo
public double Razdalja(Tocka t), ki vrne razdaljo med trenutno toko in toko t, ki jo
metoda dobi kot parameter.
Razdalja med dvema zajcema
Dopolni razred Zajec z metodo RazdaljaMedZajcema, ki kot parameter sprejme drugega zajca in
vrne razdaljo med njima.
Uporaba razreda Zajec II
Oboroeni z novimi metodami dopolnimo na program za gojenje zajcev tako, da generira zajce na
nakljunih poloajih. Nazadnje poiimo zajca, ki je:
1. najbolj oddaljen od prvega zajca
2. najbolj oddaljen od koordinatnega izhodia
3. ima najveji produkt med maso in oddaljenostjo od zhodia
Razred Ulomek
Podana je koda razreda Ulomek. Dopolni manjkajoe metode ter v glavnem programu
(metoda Main) ustvari dva ulomka, katerih tevec in imenovalec naj bo nakljuno tevilo
med med 1 in 9 (vkljuno z mejama). Ulomka setej in rezultat izpii na zaslon.
RAZRED ULOMEK
public class Ulomek {
640:
int stevec;
641:
int imenovalec;
642:
643:
644:
645:
646:
647:
648:
649:
650:
651:
652:
653:
654:
655:
656:
657:
658:
659:
660:
661:
662:
C# . NET
83
663:
// DOPOLNI!
664:
}
665:
// Metoda vrne vrednost ulomka kot realno tevilo.
666:
public DOPOLNI Vrednost() {
// DOPOLNI!
667:
668:
}
669:
670:
// Vrne niz oblike stevec/imenovalec
671:
DOPOLNI string ToString() {
672:
// DOPOLNI!
673:
}
674:
675:
// Metoda okraja dani ulomek
676:
public void Okrajsaj() {
677:
// DOPOLNI
678:
}
679:
680:
// Obratna vrednost.
681:
public void Obrni() {
682:
// DOPOLNI
683:
}
684: }
TESTNI PROGRAM
public class TestUl
685:
public static void Main(string[] argc) {
686:
// DOPOLNI po navodilih naloge!
687:
}
688: }
Razred Stranka
Na osnovi kode spodaj podanega razreda Oseba sestavite razred Stranka, ki predstavlja banno strankoega
komitenta. Poleg lastnosti, so enake kot v razredu Oseba, mora hraniti tudi podatke o tekoem raunu (niz),
tevilki EMO (niz) ter povprenem mesenem prilivu na tekoi raun (realno tevilo).
RAZRED OSEBA
public class Oseba {
private string ime;
private string priimek;
public Oseba(string ime, string priimek) {
this.ime = ime;
this.priimek = priimek;
}
public string VrniIme() {
return this.ime;
}
public string VrniPriimek() {
return this.priimek;
}
Programiranje 1 VS Informatika
C# . NET
84
}
Pri tem mora razred zadoati naslednjim pogojem:
Vse spremenljivke v njem morajo biti privatne.
Poznati mora javni konstruktor, ki sprejme pet parametrov: ime, priimek, tevilko tekoega
rauna, tevilko EMO ter podatek o povprenem mesenem prilivu na raun. Pri tem mora biti
zadnji podatek pozitivni+o realno tevilo, prvi tirje pa neprazni nizi. e to ni izpolnjeno,
ustrezno reagiraj.
Poznati mora metode za vraanje podatkov, ki jih hrani: imena, priimka, tevilke tekoega
rauna, tevilke EMO ter povprenega priliva na raun.
Metoto ToString, ki na smiselen nain izpie podatke o stranki.
Nazadnje sestavite testni program, kjer ustvarite tabelo desetih strank z izmiljenimi podatki, ter med njimi
poite stranko z najvijim mesenim prilivom na raun ter tistega z po leksikografski urejenosti prvim imenom
(e jih je ve z enakim najvejim prilivom ali enakim prvim imenom poiite kateregakoli) ter izpiite njune
podatke na zaslon (z uporabo metode ToString).
Kubini polinom
Na osnovi razreda Polinom, ki hrani polinome do stopnje dva in pozna operacijo setevanja dveh polinomov
(njegovo kodo glej spodaj) sestavi razred KubicniPolinom, ki bo lahko hranil kubine polinome ter bo poleg
vsote podpiral tudi operacijo, ki obstojei polinom pomnoi s skalarjem (spremeni torej obstojei objekt in ne
ustvari novega). Seveda naj tvoj razred ne pozabi na metodo ToString, ki v razredu Polinom manjka.
RAZRED POLINOM
//razred predstavlja polinom oblike ax^2 + bx + c
public class Polinom {
private double a, int b, int c;
//Ustvari nielni polinom.
public Polinom() {
this.a = this.b = this.c = 0;
}
//Ustvari polinom z danimi koeficienti.
public Polinom (double a, double b, double c) {
this.a = a;
this.b = b;
this.c = c;
}
public Polinom Sestej(Polinom p) {
return new Polinom(this.vrniKoeficient(2) + p.vrniKoeficient(2),
this.vrniKoeficient(1) + p.vrniKoeficient(1),
this.vrniKoeficient(0) + p.vrniKoeficient(0));
}
//metoda nam vrne koeficient pred x^i
public int VrniKoeficient(int i) {
if (i == 2)
return this.a;
if (i == 1)
return this.b;
Programiranje 1 VS Informatika
C# . NET
85
if (i == 0)
return this.c;
return 0;
}
//Metoda nastavi koeficient pred x^i na k.
//e je i napaen, naj ne stori ni
public void NastaviKoeficient (int i, double k) {
if (i == 2)
this.a = k;
else if (i == 1)
this.b = k;
else if (i == 0)
this.c = k;
}
}
Sestavi testni program, ki vsebuje metodo, ki zna odteti dva kubina polinoma (vrne polinom, ki je razlika dveh
polinomov). Namig. p1 p2 lahko izrauna kot p1 + ((-1)*p2). Pregledno izpii nekaj raunov s polinomi.
Polinom
Sestavi razred s pomojo katerega predstavi poljubni polinom. Namig: koeficiente hrani v tabeli. Razred naj
pozna enake metode kot razred KubicniPolinom.
Dalmatinci I (brez raunalnika)
Denimo, da smo eleli sestaviti razred Dalmatinec, ki ima lastnosti ime psa in tevilo njegovih pik. Koda razreda
je:
RAZRED DALMATINEC
public class Dalmatinec{
public string ime;
private int steviloPik;
public Dalmatinec() {
this.ime = "Reks";
this.steviloPik = 0;
}
public void ImePsa(string ime) {
ime = this.ime;
}
private void NastaviIme(string ime) {
this.ime = ime;
}
public void NastaviSteviloPik(int steviloPik) {
this.steviloPik = steviloPik;
}
}
V glavnem programu smo ustvarili objekt Dalmatinec z imenom d in mu elimo nastaviti tevilo pik na 100 in
ime na Pika. Kateri nain je pravilen? Pri nepravilnih povej, kaj in zakaj ni pravilno.
a) d.NastaviIme("Pika"); d.NastaviSteviloPik(100);
Programiranje 1 VS Informatika
C# . NET
86
obstaja naj metoda KaksenSpol, ki v primeru samca vrne 'm', v primeru samice pa 'f'.
spol se nastavi le ob ustvarjanju objekta. Morali boste torej napisati konstruktor razreda
Dalmatinec, ki sprejme kot parameter znak za spol. Ta naj bo kot zgoraj 'm' za samca in 'f' za
samico. Predpostavite, da bo parameter zagotovo znak 'm' ali 'f'.
Dalmatinci III
Predpostavimo, da razred, ki zadoa kriterijem naloge Dalmatinci III, e imamo. Sestavi metodo public
static int SteviloSamcev(Dalmatinec[] dalmatinci), ki preteje tevilo samcev v tabeli
dalmatincev.
Oseba
Podan imamo razred Oseba z objektnima metodama VrniIme() ter VrniPriimek() (ki nam vrneta
niza, ki predstavljata ime oz. priimek osebe). Sestavite metodi, ki:
a. iz tabele tipa Oseba[] izpie vse osebe z imeni dolgimi 5 znakov.
b. iz tabele tipa Oseba[], kjer so osebe urejene po priimkih (ter nato po imenih), uinkovito
poiite osebo Janez Novak, ter kot rezultat metode vrnite referenco na to osebo. e
takna oseba ne obstaja, vrnite null.
Oseba II
Podan imamo razred Oseba z objektnima metodama VrniIme() ter VrniPriimek() (ki nam vrneta
niza, ki predstavljata ime oz. priimek osebe). Sestavite statini metodi, ki:
a. Za dano tabelo tipa Oseba[] izpie priimke vseh oseb, katerih skupna dolina imena in
priimka presega k znakov, kjer je k parameter metode.
b. V tabeli tipa Oseba[], kjer so osebe urejene po priimkih, uinkovito poiite poljubno osebo
s priimkom Novak (ime torej ni pomembno), ter kot rezultat metode vrnite nov objekt, ki
ima podatke enake kot najdena oseba. e takna oseba ne obstaja, vrnite null.
Zgoenka
Pesem na zgoenki je predstavljena z objektom razreda Pesem:
public class Pesem
{
public string naslov;
public int minute;
public int sekunde;
Programiranje 1 VS Informatika
C# . NET
87
Statino in objektno
Statine komponente
o V razredu Kvader
public static final int MIN_DOL_STR = 1;
o final
gre za konstanto
Ni novega, e poznamo
o static
Obstajajo neodvisno od obstoja objekta tega razreda
Le en primerek za cel razred!
Math.PI
Statine spremenljivke
public class Foo {
public static int x = 13;
public int y;
public Foo(int z) {
this.y = z;
}
}
o x: statina komponenta, y: objektna (nestatina) komponenta
o Statine komponente: vsebovane v razredu, objektne komponente: v objektih.
o Vsak objekt vsebuje svojo kopijo objektnih komponent, vsaka statina komponenta pa vedno obstaja v eni
sami kopiji.
Foo t1 = new Foo(42);
Foo t2 = new Foo(30);
o Dva objekta - dve kopiji komponente y, po eno v vsakem objektu. Ker je komponenta x statina, vedno
obstaja v eni sami kopiji, tudi e nimamo nobenih objektov razreda Foo:
Programiranje 1 VS Informatika
C# . NET
88
Programiranje 1 VS Informatika
C# . NET
89
RAZRED ZAJEC
418: public class Zajec {
419:
// SKUPNE SPREMENLJIVKE
420:
private static string OsnovaSerijska = "ZAJEC_";
421:
private static int kolikoZajcev = 0;
422:
public static final int MIN_TEZA = 0; // minimalna tea
423:
public static final int MAX_TEZA = 10; // maksmialna tea
424:
// OBJEKTNE SPREMENLJIVKE
425:
426:
private string serijska;
427:
private bool spol;
428:
private double masa;
429:
// konstruktorji
430:
431:
432:
public Zajec() {
433:
this.spol = true; // vsem zajcem na zaetku doloimo m. spol
this.masa = 1.0; // in tehtajo 1kg
434:
435:
ZajecNov.kolikoZajcev++; // NAREDILI SMO NOVEGA ZAJCA
436:
this.serijska = ZajecNov.OsnovaSerijska + ZajecNov.kolikoZajcev;
437:
}
public Zajec(bool spol, double masa) {
438:
439:
this(); // poklicali smo konstruktor Zajec() - ta
// bo e poveal tevilo zajcev + naredil
440:
441:
// nj. ser. tevilko
442:
this.SpremeniTezo(masa); // uporabimo metodo za sprem.
this.spol = spol;
443:
444:
}
445:
446:
// get/set metode
447:
448: public double PovejTezo() {
449:
// teo bomo povedali le na 0.5 kg natanno
450:
int tezaKg = (int)this.masa;
int decim = (int)((this.masa - tezaKg) * 10);
451:
452:
if (decim < 3) return tezaKg + 0.0;
453:
if (decim < 8) return tezaKg + 0.5;
454:
return tezaKg + 1.0;
455: }
456:
457: public bool SpremeniTezo(double novaTeza) {
458:
// smislena nova teza je le med MIN_TEZA in MAX_TEZA
459:
if ((novaTeza > MIN_TEZA) && (novaTeza <= MAX_TEZA)){
460:
this.masa = novaTeza;
461:
return true; // sprememba uspela
462:
}
463:
// v nasprotnem primeru NE spremenimo tee
464:
// in javimo, da spremembe nismo naredili
465:
return false;
466: }
467:
468: public string PovejSerijsko() {
469:
return this.serijska;
470: }
Programiranje 1 VS Informatika
C# . NET
90
471:
472: // public void SpremeniSerijsko(string s) { TO IZLOIMO;
473:
// KER SE SER_T NE SPREMINJA!
474:
475: public bool JeSamec() {
476:
return this.spol;
477: }
478:
479: // ker se spol naknadno NE spremeni, metode za
480: // spreminjanje spola sploh ne ponudimo uporabniku!
481:
482:
// Ostale metode
483:
484: public double Vrednost(double cenaZaKg) {
485:
// pove vrednost zajca
486:
// zajce tehtamo na dogovorjeno natannost
487:
return cenaZaKg * this.povejTezo();
488: }
489:
490: public bool MeNapojiti() {
491:
// ugotovimo, e ga je smiselno
// napojiti, da bomo "ujeli" naslednjih pol kg
492:
493:
// dejanska tea je veja od "izmerjene"
494:
return (this.masa - this.povejTezo() > 0);
495: }
496:
497: } // Zajec
tetje ustvarjenih objektov
V konstruktorjih poveujemo tevec
RAZRED KVADER
498: public class Kvader {
499:
// z /* ... */ so oznaceni komentarji za razlago
500:
// zakaj doloceni konstrukcijski prijemi
501:
// v "pravem" programu jih ne bi bilo!
502:
503:
private double a; /* uporabnika ne zanima, kako
504:
imamo shranjene podatke */
505:
private double b;
private double c;
506:
507:
508:
private int serijskaStevilka; // serijska stevila objekta
509:
510:
private static int kolikoNasJe = 0; // koliko je
511:
// ustvarjenih objektov
512:
513:
public static final int MIN_DOL_STR = 1; // minimalna
514:
// dolzina stranice
515:
public static final int MAX_DOL_STR = 100; // maksimalna
516:
// dolzina stranice
517:
/* Ker menimo, da je smiselno, da uporabnik neposredno
518:
vidi ti dve kolicini - dostop
519:
public. Spreminjati ju ne more zaradi final.
520:
Dostop: Kvader.MIN_DOL_STR
Programiranje 1 VS Informatika
C# . NET
521:
522:
523:
524:
525:
526:
527:
528:
529:
530:
531:
532:
533:
534:
535:
536:
537:
538:
539:
540:
541:
542:
543:
544:
545:
546:
547:
548:
549:
550:
551:
552:
553:
554:
555:
556:
557:
558:
559:
560:
561:
562:
563:
564:
565:
566:
567:
568:
569:
570:
571:
572:
573:
574:
91
C# . NET
575:
576:
577:
578:
579:
580:
581:
582:
583:
584:
585:
586:
587:
588:
589:
590:
591:
592:
593:
594:
595:
596:
597:
598:
599:
600:
601:
602:
603:
604:
605:
606:
607:
608:
609:
610:
611:
612:
613:
614:
615:
616:
617:
618:
619:
620:
621:
622:
623:
624:
625:
626:
627:
628:
92
zgornji metodi */
c = s;
}
//...........................................
// konstruktorji
public Kvader() {
a = b = c = 1;
kolikoNasJe++;
serijskaStevilka = kolikoNasJe;
}
public Kvader(int s) {
// kocka s stranico s. e podatek ni v redu - kocka z robom 1
if (!kontrola(s)) s = 1; // ce podatek ni v mejah,
// ga postavimo na 1
a = b = c = s;
kolikoNasJe++;
serijskaStevilka = kolikoNasJe;
}
public Kvader(int s1, int s2, int s3) { // kvader s1 x s2 x s3
// Ce kak podatek ni v redu - ga postavimo na 1
if (!kontrola(s1)) s1 = 1; // ce podatek ni v mejah,
// ga postavimo na 1
a = s1;
if (!Kontrola(s2)) s2 = 1; // ce podatek ni v mejah,
// ga postavimo na 1
b = s2;
if (!Kontrola(s3)) s3 = 1; // ce podatek ni v mejah,
// ga postavimo na 1
c = s3;
kolikoNasJe++;
serijskaStevilka = kolikoNasJe;
}
public Kvader(Kvader sk) {
// Novi objekt je kopija obstojecega objekta sk
this.a = sk.a; /* this ni potreben */
StranicaB(sk.PovejB()); /* tudi znotraj razreda se
splaca uporabljati metode
za delo s podatki */
StranicaC(sk.PovejC()); /* ceprav imamo neposreden dostop
do spremenljivk, saj nam ob
morebitni spremembi predstavitve
ni potrebno toliko popravljati! */
kolikoNasJe++;
serijskaStevilka = kolikoNasJe;
}
Programiranje 1 VS Informatika
C# . NET
93
629:
630:
public static int PovejKolikoNasJe() {
631:
return kolikoNasJe;
632: }
633:
634:
//
635:
// --------------- to string
636:
//
public string ToString() { /* prekrivanje metode iz razreda
637:
638:
Object */
639:
// Metoda vrne podatek v obliki Kvader: a x b x c
640:
return "Kvader: " + PovejA() + " x " + PovejB() + " x "
641:
+ PovejC();
642:
/* tudi znotraj razreda se splaca uporabljati metode za
643:
delo s podatki ceprav imamo neposreden dostop do
644:
spremenljivk, saj nam ob morebitni spremembi predstavitve
645:
ni potrebno toliko popravljati! */
646:
}
647:
648: } // class Kvader
Zgled 2:
Uporaba konstant
Meje pravilnosti podatkov so konstantne
C# . NET
717:
718:
719:
720:
721:
722:
723:
724:
725:
726:
727:
728:
729:
730:
731:
732:
733:
734:
735:
736:
737:
738:
739:
740:
741:
742:
743:
744:
745:
746:
747:
748:
749:
750:
751:
752:
753:
754:
755:
756:
757:
758:
759:
760:
761:
762:
763:
764:
765:
766:
767:
768:
769:
770:
94
this.visina = OBI_VISINA;
}
}
// "SET" metode
public bool NastaviPolmer(int r) {
// smiselni polmer je le med 1 in NAJ_POLMER
// drugace ga pustimo pri miru
// metoda vrne vrednost true, ce smo polmer spremenili
if (Vmes(r, 1, NAJ_POLMER)) {
this.polmer = r;
return true;
}
return false; // polmer je ostal nespremenjen
}
public bool NastaviVisino(int visina) {
// smiselni polmer je le med 1 in NAJ_VISINA
// drugace jo pustimo pri miru
// metoda vrne vrednost true, ce smo visino spremenili
if (vmes(visina, 1, NAJ_VISINA)) {
this.visina = visina;
return true;
}
return false; // visina je ostala nespremenjena
}
// "GET" metode
public int PovejPolmer() {
return polmer;
}
public int PovejVisino() {
return visina;
}
// tostring
override public string ToString() {
return "Polmer: " + this.polmer + " visina: " + this.visina;
}
// volumen in povrsina
public double Volumen() {
// volumen kovanca PI * r^2 * v
return Math.PI * this.polmer * this.polmer * this.visina;
}
public double Povrsina() {
// povrsina kovanca 2 * PI * r * v + 2 * PI * r^2
return (2 * Math.PI * this.polmer) * (this.polmer + this.visina);
}
// pomozne metode
private static bool Vmes(int x, int a, int b) {
Programiranje 1 VS Informatika
C# . NET
95
771:
// ali je x med a in b
772:
return (a <= x) && (x <= b);
773: }
774: }
Statine metode
Objekt:
Objektne komponente
Objektne metode
Skupno vse objektom na nivoju razreda:
statine metode
statine komponente
Statine metode se v neobjektnih programskih jezikih imenujejo "funkcije" ali "procedure", statine
komponente pa se imenujejo "globalne spremenljivke".
Statine/objektne metode
Statino metodo bla() v razredu Foo lahko vedno izvedemo z ukazom Foo.bla(). Znotraj statine metode objekt
this ni definiran, ker se statina metode ne klie na objektu.
Objektno metodo hej() v razredu Foo lahko izvedemo, e imamo neki objekt x razreda Foo, z ukazom x.hej().
Znotraj metode hej() oznauje this objekt, na katerem je metoda poklicana.
Zgled
int p
Foo.x
int q
Foo t
Foo s
int r
=
=
=
=
=
=
Foo.G(7);
// p == 12 + 7 == 19
-3;
Foo.F(5);
// q == -3 + 5 == 2
new Foo(100);
new Foo(200);
t.G(50);
// r == 100 + (-3) + 50 == 147
Programiranje 1 VS Informatika
C# . NET
96
Statine metode
o Kadar za izvajanje ne potrebujemo objekta tega razreda.
o Praviloma ne spreminjajo stanja nekega objekta.
o Vsi podatki podani preko parametrov metode.
o Main
C# . NET
714:
715:
716:
717:
718:
719:
720:
721:
722:
723:
724:
725:
726:
727:
728:
729:
730:
731:
732:
733:
734:
735:
736:
737:
738:
739:
740:
741:
742:
743:
744:
745:
746:
747:
748:
749:
750:
751: }
97
this.visina = visina;
return true;
}
return false; // visina je ostala nespremenjena
}
// "GET" metode
public int PovejPolmer() {
return polmer;
}
public int PovejVisino() {
return visina;
}
// ToString
override public string ToString() {
return "Polmer: " + this.polmer + " visina: " + this.visina;
}
// volumen in povrsina
public double Volumen() {
// volumen kovanca PI * r^2 * v
return Math.PI * this.polmer * this.polmer * this.visina;
}
public double Povrsina() {
// povrsina kovanca 2 * PI * r * v + 2 * PI * r^2
return (2 * Math.PI * this.polmer) *
(this.polmer + this.visina);
}
// pomozne metode
private static bool Vmes(int x, int a, int b) {
// ali je x med a in b
return (a <= x) && (x <= b);
}
Privatne metode
o Tudi metode so lahko privatne (glej prejnji zgled)
objektne, statine
o private void metodaA() {...};
o private static int metodaB{...};
o Kadar metodo potrebujemo interno uporabnikom ni potrebna!
Dedovanje
Pogosto uporabljani postopki I
Imamo razred Ulomek:
Programiranje 1 VS Informatika
C# . NET
98
C# . NET
770:
771:
772: }
99
// elegantneja
}
Fd(int n)
Rt(int st)
PenUp()
PenDown()
Zgled: Denimo, da z elvo zelo pogosto izvajamo doloen postopek. Npr. riemo kvadrat. Napiemo ustrezno
metodo.
Vedno, ko z elvo riemo kvadrate, moramo napisati to metodo:
Ampak to ni "objektno":
Znanje risanja kvadratov je lastno elvi objektu
elva (objekt) naj bi znala narisati kvadrat:
Odzvati se metodi kvadrat: nekaZelva.kvadrat(100)
Imamo dostop do knjinice :
Ni problem, dopiemo metodo
Popravljati dobro preizkuen razred?
... Do not fix, until you are completely desperate ...
Kaj pa, e izvorne kode nimamo?
Dedovanje
o "razirjanje" objektov
o Naredimo nart za razred pametnih elv:
Znajo risati kvadrate
RAZRED PAMETNAZELVA
773: public class PametnaZelva : Turtle {
774:
// naredimo nov razred "pametnih zelv"
775:
public void Kvadrat(int velikost) {
776:
// Vsaka pametna zelva ve, kako se narie
777:
// kvadrat s stranico velikost
778:
int i = 1;
779:
while (i <= 4) {
780:
base.Fd(velikost); // lahko tudi brez base
781:
// metoda fd je podedovana iz razreda Turtle
782:
base.Rt(90);
783:
// metoda rt je podedovana iz razreda Turtle
Programiranje 1 VS Informatika
C# . NET
784:
785:
786: }
100
}
}
Programiranje 1 VS Informatika
C# . NET
101
ZLATNIK -SKICA
800: public class Zlatnik : Kovanec {
801:
802:
private static double vrednostCistegaZlata = 125.4;
803:
// za vse zlatnike je to enako!
804:
805:
private int polmer;
private int visina;
806:
807:
private double gostota;
private double cistost;
808:
809:
// "SET" metode
810:
public bool NastaviPolmer(int r) { }
public bool NastaviVisino(int visina) { }
811:
812:
public void NastaviGostoto(double x) { }
public void NastaviCistost(double x) { }
813:
814:
public static void NastaviVrednostCistegaZlata(int v) { }
815:
// vrednost lahko spreminajmo tudi, ce se ni nobenega zlatnika!
816:
// "GET" metode
817:
818:
public int PovejPolmer() { }
public int PovejVisino() { }
819:
820:
public double PovejGostoto() { }
public double PovejCistost() { }
821:
822:
public static double PovejVrednostCistegaZlata() { }
823:
// vrednost lahko zvemo tudi, ce se ni nobenega zlatnika!
824:
825:
// tostring
override public string ToString() { }
826:
827:
// podedovana tostring metoda nam ne ustreza!
828:
// "znanje"
829:
830:
public double Volumen() { }
831:
public double Povrsina() { }
832:
public double Vrednost() {}
833: }
S krepko, leeo pisavo smo oznaili tistio, kar smo podedovali. Tega ne piemo v razredu!!
RAZRED ZLATNIK
834: public class Zlatnik : Kovanec {
835:
836:
private static double vrednostCistegaZlata = 125.4;
837:
// za vse zlatnike je to enako!
838:
839:
private double gostota;
840:
private double cistost;
841:
public static double OBI_GOSTOTA = 19.3; // obicajna gostota g/cm^3
842:
public static double OBI_CISTOST = 0.81; // obicajna cistost
843:
844:
/* TA del NE spada v razred, je podedovan iz razreda Kovanec
845:
tukaj ga napisemo v komentar le zaradi preglednosti pri
846:
uenju - pravi program ga NE BI vseboval !!
847:
Programiranje 1 VS Informatika
C# . NET
848:
849:
850:
851:
852:
853:
854:
855:
856:
857:
858:
859:
860:
861:
862:
863:
864:
865:
866:
867:
868:
869:
870:
871:
872:
873:
874:
875:
876:
877:
878:
879:
880:
881:
882:
883:
884:
885:
886:
887:
888:
889:
890:
891:
892:
893:
894:
895:
896:
897:
898:
899:
900:
901:
102
C# . NET
902:
903:
904:
905:
906:
907:
908:
909:
910:
911:
912:
913:
914:
915:
916:
917:
918:
919:
920:
921:
922:
923:
924:
925:
926:
927:
928:
929:
930:
931:
932:
933:
934:
935:
936:
937:
938:
939:
940:
941:
942:
943:
944:
945:
946:
947:
948:
949:
950:
951:
952:
953:
954:
955:
103
if (v > 0)
vrednostCistegaZlata = v; // vsaka pozitivna vrednost je OK
}
// "GET" metode
/* Ta del NE spada v razred, je podedovan iz razreda Kovanec
tukaj ga napisemo v komentar
le zaradi preglednosti pri uenju - pravi program ga
NE BI vseboval !!
public int PovejPolmer()
public int PovejVisino()
*/
public double PovejGostoto() {
return this.gostota;
}
public double PovejCistost() {
return this.cistost;
}
public static double PovejVrednostCistegaZlata() {
return vrednostCistegaZlata;
}
// tostring
public override string ToString() {
return "Polmer: " + base.PovejPolmer() + // zakaj ne gre
// this.polmer!
" visina: " + base.PovejVisino() +
" gostota: " + this.gostota +
" cistost: " + this.cistost;
}
/*
*/
public double Vrednost() {
// vrednost je volumen * gostota * cistost * vrednost enote
// metodo volumen dobimo iz Kovanca!
return base.Volumen()* gostota * cistost * vrednostCistegaZlata;
}
// pomozne metode
private static double SmiselnaGostota(double gostota) {
// vrne smiselno gostoto
final double DOPUSTNO_ODSTOPANJE = 0.1;
Programiranje 1 VS Informatika
C# . NET
956:
957:
958:
959:
960:
961:
962:
963:
964:
965:
966:
967:
968:
969:
970:
971: }
104
// ce so podatki "neumni"
RAZRED ZLATNIK -
ZARES
C# . NET
1008:
1009:
1010:
1011:
1012:
1013:
1014:
1015:
1016:
1017:
1018:
1019:
1020:
1021:
1022:
1023:
1024:
1025:
1026:
1027:
1028:
1029:
1030:
1031:
1032:
1033:
1034:
1035:
1036:
1037:
1038:
1039:
1040:
1041:
1042:
1043:
1044:
1045:
1046:
1047:
1048:
1049:
1050:
1051:
1052:
1053:
1054:
1055:
1056:
1057:
1058:
1059: }
105
Programiranje 1 VS Informatika
C# . NET
106
Iz muhe slon
Ne, iz muhe ne bomo naredili slona, ampak pri nas zajci postanejo ovce.
Pri nas se je oglasil bogati Rus, ki je bil tako navduen nad naim programom za vodenje farme zajcev, da hoe,
da mu zanj pripravimo podoben program.
Posebno nad metodo MeNapojiti() je bil navduen!
A al on ne vodi farme zajcev, ampak farmo ovac.
Poleg tega, da ovce redi za zakol, prodaja tudi njihove kouhe, zato bi rad, da vodimo e barvo njihovega
kouha.
Osnova: razred ZajecNov
Kakne spremembe so potrebne?
Napane lastnosti:
OsnovaSerijska ni OK
Prav tako MAX_TEZA
Dodati lastnosti:
Barva kouha
Get/set metodi:
denimo, da si tudi ovce barvajo kouhe
Popraviti konstruktor in dodati metodo ToString:
V razredu ZajecNov smo nanjo pozabili!
Prekrite metode
o
o
o
o
o
o
"Umazane" podrobnosti
o
o
o
o
o
o
o
base()
serijska ponovno!
ker zaradi private ne moremo do serijska iz ZajecNov
PovejSerijska() na novo
enaka e v ZajecNov
Razlog: nova spremenljivka serijska
e ne navedemo - metoda bi vraala serijsko iz zajcev!!
Uporaba
C# . NET
107
1069:
System.Console.WriteLine(z1
z1.Vrednost(12.8));
1070:
}
1071: }
"
Vredna
sem
"
Zgledi
Vaje
Razred Kovanec
Sestavi razred Kovanec, s katerim predstavimo kovance.
Denimo, da so kovanci okrogli, z danim polmerom in viino. Poleg konstruktorjev in standardnih metod, ki
nastavijo in vrnejo vrednosti lastnosti in za pretvorbo v niz, naj razred pozna e metodi, ki vrneta povrino in
volumen kovanca.
Razred Zlatnik
Sestavi razred Zlatnik, ki deduje iz razreda Kovanec. Zlatnik ima poleg osnovnih lastnosti kovanca
podano e gostoto materiala, iz katerega je izdelan, istoo zlata (podano z realnim tevilom med 0 in 1) in
vrednost istega zlata na masno enoto. Napii get in set metode za nastavljanje in branje dodanih komponent.
Razred naj pozna tudi metodo double Vrednost(), ki vrne vrednost zlatnika.
Namig:
Vrednost istega zlata je enaka za VSE zlatnike, torej je razredna spremenljivka ( static)
Razred BoljsiZlatnik
V deeli Fiksniji so se odloili prevzeti finanni sistem deele Spremenije, kjer je bila osnovna enota zlatnik,
opisan v razredu Zlatnik.
Vladar Fiksnije se je temu dolgo upiral, a na koncu le popustil. Zahteval pa je: V deeli bodo le ene vrste zlatniki
in njihove lastnosti se ne smejo spreminjati.
Svetovalci so ga opozarjali, da bo vsa stvar videti preve diktatorska, e ne bo na voljo vsaj navideznih monosti
sprememb. Zato so mu svetovali, naj obdri vse monosti razreda Zlatnik, a le navidezno, torej tako, da bo
vse ostalo nespremenjeno.
Tvoja naloga je, da pripravi razred BoljsiZlatnik, ki bo tak, kot Zlatnik iz Spremenije, le da
upoteva zahteve vladarja Fiksnije, ohrani vse metode razreda Zlatnik na zunaj enake, a jih predrugai
tako, da ne bodo omogoale sprememb.
Razred Ovca
Pri tebi se je oglasil bogati Rus, ki je bil tako navduen nad tvojim programom za vodenje farme zajcev, da hoe,
da mu zanj pripravi podoben program.
Vendar on ne vodi farme zajcev, ampak farmo ovac. Poleg tega, da ovce redi za zakol, prodaja tudi njihove
kouhe, zato bi rad, da vodimo e barvo njihovega kouha.
Iz razreda Zajec izpelji razred Ovca, razredu Ovca dodaj lastnost barvaKouha in napii get in set
metodo za to lastnost (recimo, da si tudi ovce barvajo kouhe ). Ustrezno popravi konstruktorje.
Napii tudi metodo toString , ki bo prekrila metodo toString iz razreda Zajec in bo vrnila smiselen
izpis podatkov o ovci.
Zival
Sestavi razred Zival, ki vsebuje spremenljivke
o private int steviloNog;
o private String vrsta;
o private String ime;
in metode za nastavljanje in spreminjanje le-teh. Vsebuje tudi konstruktor brez parametrov, ki postavi
spremenljivke na smiselno zaetno vrednost.
Programiranje 1 VS Informatika
C# . NET
108
Dopolnite razred z metodo public string toString(), ki naj izpie podatke o razredu v obliki:
#Ime: je vrste #vrsta in ima #steviloNog nog.
Pri tem seveda zamenjajte #vrsta in #steviloNog z vrednostmi v istoimenskih spremenljivkah. Nato
napiite testni program, kjer ustvarite 5 ivali in jim nastavite smiselno vrsto in imena ter tevilo nog.
Izpiite jih!
Vzemi razred Kvader in iz njega izpelji razred Kocka. Dodaj mu konstruktor, ki sprejme le en parameter in
pravilno nastavi irino, viino in globino (objektne spremenljivke v razredu Kvader).
Seveda obstaja problem, da lahko uporabnik od zunaj preko metod NastaviSirino, NastaviGlobino in
NastaviVisino spremeni nao kocko v kvader - zaenkrat to pustimo ob strani.
Sestavi tudi testni program, kjer ustvari nekaj kock in izpie njihovo povrino in volumen.
775:
776:
777:
778:
779:
780:
781:
782:
783:
784:
785:
786:
787:
788:
789:
790:
791:
792:
793:
794:
795:
796:
797:
798:
799:
800:
801:
802:
803:
804:
805:
806:
807:
808:
809:
810:
811:
812:
813:
814:
C# . NET
815:
816:
817:
818:
819:
820:
821:
822:
823:
824:
825:
826:
827:
828:
829:
830:
831:
832:
833:
834:
835:
836:
837:
838:
839:
109
Povrsina() {
* this.VrniSirino() * this.VrniVisino() +
* this.VrniGlobino() * this.VrniVisino() +
* this.VrniSirino() * this.VrniGlobino();
Razred Pes
Iz razreda Zival izpelji razred Pes. Razred naj vsebuje dodatne metode:
o public void NastaviPasmo(String pasma): e uporabnik "podtakne" prazen niz, naj vre
napako!
o public String VrniPasmo()
o public void NastaviStarost(int starost): poskrbite, da bo starost vedno med 1 in 25 let.
o public int VrniStarost()
Seveda boste za hrambo dodatnih podatkov rabili nekaj dodatnih objektnih spremenljivk. Poskrbi tudi, da bo
osnovni konstruktor razreda Pes nastavil vrsto na pes, tevilo nog na tiri ter pasmo in starost postavil na
smiselno vrednost (naredite tabelo vsaj desetih pasem in izbirajte med njimi). Nato vsakemu objektu nekajkrat
(nakljuno mnogokrat) spremenite pasmo in tevilo nog.
Ko boste ustvarili razred, dopolnite testni program tako, da vam namesto petih ivali ustvari pet objektov tipa
Pes.
Denimo, da nas zanima statistika ustvarjanja objektov, in sicer:
o
o
o
Dopolni program tako, da bo na koncu delovanja te podatke izpisal. Namig: razredne spremenljivke (kljuna
beseda: static).
Razred Dalmatinec
Iz razreda Pes izpelji razred Dalmatinec. Razred naj vsebuje dodatne metode:
o
o
public void NastaviSteviloPik(int pike): poskrbi za to, da bo tevilo pik med 1 in 1000.
public int VrniSteviloPik()
Programiranje 1 VS Informatika
C# . NET
110
public int VrniVrednost(): vrne vrednost dalmatinca glede na njegovo starost in tevilo pik.
Ve ko ima pik, ve naj bo vreden, in sicer naj bo vsaka pika vredna 1000 - #steviloLet tolarjev.
Poleg tega je e omejitev na zgornjo in spodnjo ceno: dalmatinec ne more stati ve manj kot
10000SIT in ne ve kot 1000000 SIT.
Dopolni testni program tako, da ustvari 100 dalmatincev z nakljunim tevilom pik. Poii med njimi
najdrajega in ga izpii! e je taki dalmatincev ve, izpii vse.
Naloge brez raunalnika
1. Kakna je razlika med statinimi in dinaminimi spremenljivkami oz. metodami v razredu? Katere izmed
spodnjih trditev o dinaminih/statinih spremenljivkah v razredu so pravilne?
Za dostop do statine spremenljivke oz. metode ne potrebujemo primerka razreda.
Za dostop do dinamine spremenljivke oz. metode ne potrebujemo primerka razreda.
e posebej ne poudarimo, je metoda statina.
Objekt razreda lahko klie statino metodo oz. dostopa do statine spremenljivke.
2.
840:
841:
842:
843:
844:
845:
846:
847:
848:
849:
850:
851:
852:
853:
854:
855:
3.
C# . NET
872:
873:
874:
875:
876:
877:
878:
879:
880:
881:
882:
883:
884:
885:
886:
887:
888:
889:
890:
891: }
111
else
numOther++;
}
public string GetName() {
return name;
}
public String GetCountry() {
return country;
}
public int GetAge() {
return age;
}
public void IncreaseAge() {
age++;
}
C# . NET
112
spremenite razred Zival tako, da mu dodate konstruktor, ki sprejme vrsto, tevilo nog in ime
ivali in jih nastavi na smiselne vrednosti. Za nastavljanje uporabite metode NastaviXyz, saj le
te preverijo tudi pravilnost podatkov!
uporabniku onemogoite spreminjanje tevila nog in vrste ivali tako, da spremenite tip
metode v protected. Metodo sedaj lahko uporabljamo interno v razredu in v vseh iz njega
izpeljanih razredih, le uporabnik je ne more klicati "od zunaj". Popravi tudi testni program za
razred Zival!
denimo, da nas pri razredu Zival moti, ker moramo za vse vrste ivali podajati tevilo nog,
eprav je to pravzaprav e v naprej znan podatek. Zato razred dopolnite z dvema razrednima
tabelama (torej tipa static, saj bosta za vse objekte tipa Zival vedno enaki) string[] pasme in
int[] steviloNog, kjer v prvo vpiemo nekaj pasem, v drugo pa na isto mesto vpiemo tevilo
nog, ki pripada tej vrsti.
dopolni metodo nastaviVrsto tako, da v primeru poznane vrste (takne, ki je v nai tabeli),
pravilno nastavi tudi tevilo nog ivali.
napii tudi konstruktor, ki sprejme le ime in pasmo ivali in pravilno nastavi tevilo nog. e mu
pasma ni poznana, naj uporabnika vpraa e za tevilo nog in poklie star konstruktor, ki
sprejme vse parametre. Ustrezno popravite tudi testni program,
napiite nov konstruktor v razredu Pes, ki sprejme pasmo in ime psa, tevilo nog in vrsto ivali
pa nastavi na 4 oz. na "pes".
V nei prejnjih vaj smo iz razreda Kvader izpeljali razred Kocka, ki je preko konstruktorja nastavil viino, irino in
globino kvadra na enake vrednosti (dolino stranice kocke).
Obstajal pa je problem, da je uporabnik lahko od zunaj preko metod nastaviSirino, nastaviGlobino oz.
nastaviViino nao kocko spremenil v kvader. Ker pa poznamo prekrivanje metod, znamo to storiti bolje: prekrij
metode za nastavljanje globine, irine in viine v razredu Kvader tako, da bodo spreminjale edino mero za
kocko. Razredu Kocka dodaj tudi dodatni metodi public void NastaviStranico(double a) in public double
PreberiStranico(), ki nastavi oz. vrne dolino stranice kocke. Pri tem bodi pozoren na veljavnost podatkov!
Prekrij tudi metodo public string ToString().
Razred Kocka je nastavil viino, irino in globino kocke v konstruktorju z uporabo metod NastaviSirino,
NastaviGlobino in NastaviVisino baznega razreda. Spremeni kodo tako, da bo konstruktor razreda Kocka, ki kot
parameter dobi dolino stranice kocke, klical konstruktor razreda Kvader in mu podal irino, viino in globino
kocke, ki jo ustvarjamo (torej tri enaka tevila).
Vpraanje: kako lahko sedaj iz razreda Kocka kliemo metode NastaviSirina, NastaviGlobina in NastaviVisina iz
razreda Kvader?
Novi razred Kocka tudi preizkusi: ustvari testni program, kjer naredi tabelo vsaj 100 kock z nakljuno dolgimi
stranicami med 10 in 100 enot. Poizkusi jim nastaviti irino, viino in globino. Med njimi poii kocki z najvejo
povrino in prostornino ter ju izpii.
Podoben problem kot pri razredu Kocka smo imeli tudi pri razredu Pes, kjer je uporabnik lahko spreminjal vrsto
ivali in tevilo njenih nog preko metod v razredu Zival.
Problem smo reili tako, da smo uporabniku popolnoma onemogoili dostop do metod za spreminjanje tevila
nog in vrste ivali, kar pa ni najlepa reitev. Zato spremeni razred Pes tako, da prekrije metodi za nastavljanje
tevila nog in vrste ivali - naj enostavno ne naredita ni!
e metode res delujejo kot je potrebno preverite s testnim programom, kjer poskusite spremeniti vrsto in
tevilo nog objekta tipa Pes.
Razred Dalmatinec iz prejnjih vaj dopolni z lastnostma maksimalna hitrost (celo tevilo med 10 in 50
kilometrov na uro) in poloaj (poloaj dalmatinca v ravnini - je spremenljivka tipa Tocka, ki smo jo naredili v eni
prejnjih nalog).
Razred mora seveda imeti tudi metode za branje oz. spreminjanje hitrosti oz. poloaja dalmatinca. Pazi na to,
da preveri podatke preden jih nastavi!
Ustvari tudi testni program, kjer ustvari 100 nakljunih dalmatincev, ki so razporeni na nakljunih lokacijah na
ravnini (nakljuni dalmatinec pomeni, da je nakljuno star, hiter in ima nakljuno mnogo pik). Nato med njih na
Programiranje 1 VS Informatika
C# . NET
113
nakljuno toko vri klobaso. e predpostavimo, da se v trenutku ko klobasa prileti med njih vsi dalmatinci
naenkrat zapodijo ponjo, kateri jo bo dobil prvi? Izpii ga.
Poii tudi najblija in najbolj oddaljena dalmatinca in ju izpii.
Zajec iz ivali
Iz razreda Zival izpelji razred Zajec. Poleg osnovnih lastnosti iz razreda Zival naj pozna e:
o
o
o
tipu embalae: ker izdelujejo le konno mnogo tipov embalae, se sme tip izbrati le
izmed nekaj v naprej definiranih. V razredu Embalaza zato definirajte tabelo nizov, ki
predstavljajo dovoljene tipe embalae. Tip embalae naj bo mono spremeniti tako,
da direktno povemo tip embalae kot niz ali pa tako, da podamo indeks tipa
embalae v tabeli tipov. e tak tip embalae ne obstaja, naj se vre napaka. Poznamo
vsaj plastino in kartonsko embalao.
obliki embalae: za obliko veljajo enaka pravila kot za tip, le da zaenkrat poznamo le
oblike: kocka, tetraeder in valj.
barvo embalae: barva je lahko poljuben neprazen niz.
maso embalae: pozitivno tevilo.
ceno izdelave: ker cene izdelave za splono embalao ne poznamo, naj bo
nastavljena na 0.
Seveda mora razred vsebovati metode za nastavljanje in branje teh lastnosti ter vsaj konstruktor brez
parametrov, ki ustvari embalao s smiselnimi lastnostmi. Poleg tega podjetje zanima tudi, koliko embalae so
izdelali. V ta namen bo potrebno v razred dodati razredno spremenljivko, ki se povea vsaki ko se ustvari nov
objekt tipa Embalaza in metodo, ki vraa njeno vrednost. Nikakor pa ne smete dodati metode za spreminjanje
te vrednosti! Zakaj?
Seveda je takna embalaa e povsem neuporabna (ne vemo npr. na kakni temperaturi jo lahko skladiimo...),
dodatne lastnosti embalae pa so mono odvisne od materiala, iz katerega je embalaa izdelana. Denimo, da
nas trenutno najbolj zanima plastina embalaa. Zato iz razreda Embalaza izpelji razred PlasticnaEmbalaza, ki
vsebuje lastnosti:
C# . NET
114
C# . NET
115
904:
this.barva = barva;
905:
this.maxHitrost = 100;
906:
this.steviloKoles = steviloKoles;
907: }
908:
909: private Vozilo(int steviloKoles, string barva, int maxHitrost) {
910:
this.barva = barva;
911:
this.maxHitrost = maxHitrost;
this.steviloKoles = steviloKoles;
912:
913: }
914:
915: public Tovornjak Klonirajv0() {
916:
return new Tovornjak(this.steviloKoles, this.barva,
917:
this.maxHitrost);
918: }
919:
920:
921: public Tovornjak Klonirajv1() {
return new Tovornjak(this.steviloKoles, this.barva,
922:
923:
this.maxHitrost, nosilnost);
924: }
925:
926: public Tovornjak Klonirajv2() {
927:
return new Tovornjak(this.steviloKoles, this.barva,
928:
this.maxHitrost, 1000);
929: }
930:
931: public void Hitrost(int mh) {
932:
this.maxHitrost = mh;
933: }
934:
935: public int JeHitrost() {
936:
return this.maxHitrost;
937: }
938: public string Barva() {
939:
return this.barva;
940: }
941:
942: override public string ToString() {
943:
return "Avtomobil barve " + barva + " s " +
944:
steviloKoles + " kolesi razvije najvecjo hitrost "
945:
+ maxHitrost;
946: }
947:
948: }
in
C# . NET
116
955: }
956:
957: public Tovornjak(string barva) : base(8, barva) {
958: }
959:
960: public Tovornjak(int maxHitrost) : this() {
961:
this.maxHitrost = maxHitrost;
962: }
963:
964: public Tovornjak(int steviloKoles, string barva, int maxHitrost) :
965:
base(steviloKoles, barva, maxHitrost) {
966:
this.nosilnost = 10000;
967: }
968:
969: public Tovornjak(int steviloKoles, string barva, int maxHitrost,
970:
int nosilnost) : base(steviloKoles, barva) {
971:
this.Hitrost(maxHitrost);
972:
this.nosilnost = nosilnost;
973: }
974:
975: public Vozilo Klonirajt0() {
return new Vozilo(this.steviloKoles, this.barva, this.maxHitrost);
976:
977: }
978:
979: public Vozilo Klonirajt1() {
980:
return new Vozilo(this.steviloKoles, this.barva());
981: }
982:
983: public Vozilo Klonirajt2() {
984:
Vozilo a = new Vozilo(this.steviloKoles, this.barva());
985:
a.Hitrost(this.JeHitrost());
return a;
986:
987: }
988:
989: public override string ToString() {
990:
return "Tovornjak barve " + this.Barva() + " s "
991:
+ steviloKoles + " kolesi ima nosilnost " +
this.nosilnost;
992: }
993: }
o
o
o
500);
C# . NET
6.
117
Denimo, da smo eleli sestaviti razred Dalmatinec, ki ima lastnosti ime in tevilo pik. Koda razreda je:
1002:
1003:
1004:
1005:
1006:
1007:
1008:
1009:
1010:
1011:
1012:
1013:
1014:
1015:
1016:
1017:
1018:
1019:
1020:
1021:
V glavnem programu smo ustvarili objekt Dalmatinec z imenom d in mu elimo nastaviti tevilo
pik na 100 in ime na Pika. Kateri nain je pravilen? Pri nepravilnih povej, kaj in zakaj ni
pravilno.
h) d.NastaviIme("Pika"); d.NastaviSteviloPik(100);
i) d.ime = "Pika"; d.steviloPik = 100;
j) d.ime = "Pika"; d.NastaviSteviloPik(100);
k) d.ImePsa("Pika"); d.NastaviSteviloPik(100);
l) d.ImePsa("Pika"); d.steviloPik = 100;
m) d.NastaviIme("Pika"); d.steviloPik = 100;
n) nobeden, ker tega sploh ne moremo storiti
Sedaj elimo naemo razredu Dalmatinec dodati tudi podatke o spolu psa. Ta podatek bomo hranili v
spremenljivki spol. Interno (znotraj razreda) naj logina vrednost true pomeni enski, false pa moki spol.
Dopolnite razred tako, da bo zadoal naslednjim trem pogojem:
a)
b) obstaja naj metoda kaksenSpol, ki v primeru samca vrne 'm', v primeru samice pa 'f'.
c)
spol se nastavi le ob ustvarjanju objekta. Morali boste torej napisati konstruktor razreda
Dalmatinec, ki sprejme kot parameter znak za spol. Ta naj bo kot zgoraj 'm' za samca in 'f' za
samico. Predpostavite, da bo parameter zagotovo znak 'm' ali 'f'.
C# . NET
1025:
1026:
1027:
1028:
1029:
1030:
1031:
1032:
1033:
1034:
1035:
1036:
1037:
1038:
1039:
1040:
1041:
1042:
1043:
1044:
1045:
1046:
1047:
1048:
1049:
1050:
1051:
1052:
1053:
1054:
1055:
1056:
118
// PO POTREBI DOPOLNI
// DO SEM
// konstruktorji
public Dalmatinec() {
this.ime = "Reks";
this.steviloPik = 0;
}
// PO POTREBI DOPOLNI
// DO SEM
public void ImePsa(string ime) {
ime = this.ime;
}
private void NastaviIme(string ime) {
this.ime = ime;
}
public void NastaviSteviloPik(int steviloPik) {
this.steviloPik = steviloPik;
}
// kaken spol ima (metoda kaksenSpol)
// PO POTREBI DOPOLNI
// DO SEM
}
Predpostavimo, da razred, ki zadoa zgornjim kriterijem, e imamo. Sestavi metodo public static int
steviloSamcev(Dalmatinec[] dalmatinci), ki preteje tevilo samcev v tabeli dalmatincev.
Halo Kitajc
Po koncu prejnje naloge morate imeti tri razrede: Embalaza, PlasticnaEmbalaza in KartonEmbalaza. Uporabite
jih za reitev sledeih problemov:
o
Podjetu "Halo, Kitajc!" se je nabralo kar nekaj kosov plastine in kartonske embalae (1000
kosov vsake). Upotevajte, da so embalae razlinih te, oblik, varv, tipov plastike... zato jih
nakljuno generirajte. Ker so se sklenili porabiti zalogo, za vsako naroilo posebej vzamejo
najprimernejo (beri najcenejo) embalao, ki je ustrezna. Pomagaj jim izbati najprimernejo
embalao, e za vsako naroilo pozna teo blaga, ki ga je potrebno dostaviti in ali je blago
hrana.
Podatke o naroilu nakljuno generiraj - naroil naj bo vsaj 100 in ko enkrat neko embalao
porabi, je ne sme ve uporabiti.
Prevozniki so podjetje opozorili, da vsaka oblika embalae ni primerna za vse vrste transporta.
Tako na letala sprejemajo le embalao v obliki kocke, za transport mleka hoejo le tetraedre...
Zato poleg vsakega naroila izve e, kakne oblike naj bo embalaa. Poii najcenejo!
Za dostavo nekega zdravila zdravnika zbornica zahteva, da je zapakirano v embalai iz
plastike tipa HDPE ali PETE, ki mora biti valjaste oblike in mora imeti nosilnost vsaj 200% vijo,
kot je dejanska masa zdravila. Poii najprimernejo embalao, e ti povedo maso zdravila.
Programiranje 1 VS Informatika
C# . NET
119
Na koncu leta so v podjetju delali inventuro in zanimalo jih je, koliko denarja lahko dobijo s
prodajo vse embalae, ki jim je ostala. Pomagaj jim in izraunaj skopno vrednost vseh vrst
embalae e ve, da je v tem asu embalaa v obliki kocke izgubila 10%, emblaa v obliki valja
20% in embalaa v obliki tetraedra 30% svoje vrednosti.
Trojiko
Sestavi razred Trojisko, v katerem hranimo tevila v trojikem zapisu kot nize z obveznim predznakom.
Tako tevilo 13 zapiemo kot '+111', tevilo -5 pa kot '-12'. Razred naj vsebuje:
konstruktor public Trojisko(), ki ustvari nov objekt, v katerem hranimo tevilo z
vrednostjo 3.
metodo override public String ToString(), ki vrne tevilo v trojiki obliki, a brez
predznaka, e je le-ta pozitiven.
Zmnozi(Trojisko
Redki vektorji
Redek vektor je vektor, ki vsebuje veliko niel. Taken vektor namesto z obiajno tabelo predstavimo s
seznamom nenielnih elementov, kjer poleg vsakega elementa hranimo e indeks tega elementa v tabeli.
Seznam je naraajoe urejen po indeksih. Na osnovi sheme razreda RedekVektor podane spodaj, sestavi
ustrezni razred, potreben za predstavitev redkega vektorja. Dopolni razred Naloga1 s statino metodo, ki
seteje dva redka vektorja. Rezultat naj bo nov redek vektor (sumanda ostaneta nespremenjena). Primer
(neformalen zapis!):
{(2,1),(5,3),(-1,6)}
{(3,1),(8,2),(1,6),(3,15)} =
{(5,1),(8,2),(5,3),(3,15)}
C# . NET
1072:
1073:
1074:
1075:
1076:
1077:
1078:
1079:
1080:
1081:
1082:
1083:
1084:
1085:
1086:
1087:
1088:
1089:
1090:
1091:
1092:
1093:
1094:
1095:
1096:
1097:
1098:
1099:
1100:
1101:
1102:
1103:
1104:
1105:
1106:
1107:
1108:
120
Plavalec
Podan imamo razred Oseba z objektnima metodama VrniIme() ter VrniPriimek() (ki nam vrneta
niza, ki predstavljata ime oz. priimek osebe).
Iz zgoraj opisanega razreda Oseba, ki poleg zgoraj omenjenih metod pozna e metode za nastavljanje imena
(NastaviIme) in priimka (NastaviPriimek) ter konstruktor Oseba(), ki naredi osebo z imenom Janez in
priimkom Novak, izpeljite razred Plavalec, ki poleg imena in priimka vsebuje e podatke o:
Programiranje 1 VS Informatika
C# . NET
121
ter metode za branje in spreminjanje lastnosti (pri tem pazite na pravilnost podatkov) plavalca. Vsebuje naj tudi
objektno metodo public void Zapisi (string imeDatoteke), ki podatke o plavalcu zapie v
datoteko z imenom imeDatoteke. Vanjo naj se zapie vrstica
Plavalec #ime #priimek plava #slog.
kjer namesto #ime, #priimek ter #slog vstavite prave vrednosti.
Sestavite tudi testni program, kjer ustvarite plavalca Danijel Animer, starega 20 let, ki plava prsno, ter podatke
o njem zapiite v datoteko c:\plavalec.txt.
Plavalec II
Podan imamo razred Oseba z objektnima metodama VrniIme() ter VrniPriimek() (ki nam vrneta
niza, ki predstavljata ime oz. priimek osebe).
Iz zgoraj opisanega razreda Oseba, ki poleg zgoraj omenjenih metod pozna e metode za nastavljanje imena
(NastaviIme) in priimka (NastaviPriimek) ter konstruktor Oseba(), ki naredi osebo z imenom Janez
in priimkom Novak, izpeljite razred Plavalec, ki poleg imena in priimka vsebuje e podatke o:
najljubem stilu plavanja plavalca (indeks ustreznega stila, ki ustrezna vnosu iz spodaj omenjene tabele
e je npr. v tabeli stilov plavanja niz "prsno" na 2. tem mestu v tabeli, in elimo za tega plavalca povedati,
da najraje plava prsno, imamo tu shranjeno 2, e je "vseeno" in je niz "vseeno" v tabeli na zaetku, pa
imamo shranjeno 0)
monih stilih plavanja (tabela nizov) tabela vsebuje vsaj nize "vseeno", "kravl" in "prsno". Tabela se nikoli
ne spreminja!
ter potrebni metodi za branje (vrne naj opisno ime stila iz tabele stilov in ne indeks) in spreminjanje najljubega
stila posameznega plavalca (parameter je ime stila). e parameter pri tej metodi, ki oznauje stil, v tabeli stilov
ne obstaja, nastavimo najljubi stil plavanja na "vseeno" (torej shranimo podatek 0). Vsebuje naj tudi objektno
metodo public void Zapisi (string imeDatoteke), ki podatke o plavalcu zapie v datoteko z
imenom imeDatoteke. Vanjo naj se zapie vrstica
Plavalec #ime #priimek plava #slog.
kjer namesto #ime, #priimek ter #slog vstavite prave vrednosti (v datoteki naj bo izkljuno ta vrstica).
Sestavite tudi testni program, kjer ustvarite plavalca Danijel Animer, ki najraje plava prsno, ter podatke o njem
zapiite v datoteko c:\plavalec.txt.
Programiranje 1 VS Informatika
C# . NET
122
Razred - class
Pojem razred (class) je temeljni pojem objektno (predmetno) orientiranega programiranja. Kreirati nov razred
pomeni sistematino urediti podatke in informacije, ter manipulacije nad njimi v neko pomensko celoto.
Takno urejanje podatkov in informacij je nekaj, kar je obiajen pojav tudi v vsakdanjem ivljenju in ne velja le
za programiranje. Kot primer iz vsakdanjega ivljenja vzemimo pojem avto: vsi avtomobili imajo nekaj skupnih
zmonosti (lahko jih usmerjamo oz. vodimo, lahko jih zaustavimo, pospeujemo, itd. ) in nekaj skupnih lastnosti
oz. atributov ( imajo volanski obro, pogonski motor, kolesa itd.). Ko torej pomislimo na avto, takoj vemo, da
gre za pojem oz. objekte ki si delijo prej omenjene skupne lastnosti in zmonosti. Klasificiranje oz. razvranje
pojmov v neko celoto je torej temeljna spretnost, ki je lastna vsem ljudem in brez katere si teko zamiljamo,
kako bi ljudje razmiljali in komunicirali med seboj. Prav zaradi tega so tudi programerji prili na idejo, da bi
posamezne pojme, njihove lastnosti (atribute) in operacije nad njimi, zdruili v neko celoto, ki so jo poimenovali
razred class. Prav to pa je natanko tisto, kar nam ponujajo moderno zasnovani objektno orientirani
programski jeziki, kot je npr. Microsoft Visual C#. Omogoajo definicijo novih razredov, ki v sebi zdruujejo
lastnosti (atribute oz. podatke) in operacije nad njimi oz obnaanje (metode).
Sveta trojica predmetno usmerjenega programiranja so pojmi enkapsulacija, dedovanje in polimorfizem
Enkapsulacija
Glavni del pojma enkapsulacija predstavlja besedica kapsula: enkapsulacija pomeni postaviti nekaj v kapsulo.
Za kapsulo je znailno, da ima vidno (javno) povrino in nevidno (zasebno) notranjost, v kateri se nekaj nahaja.
Vsak predmet ali pojem si lahko ponazorimo s kapsulo. Povrino predstavljajo podatki in operacije, ki jih lahko
od zunaj spreminjamo. Notranjost pa so zasebni deli predmeta, ki od zunaj niso dostopni.
Tudi v svetu programiranja poznamo dve pomembni uporabi oz razlagi pojma enkapsulacija:
Princip, kako v enoto zdruimo podatke in metode, ki operirajo nad temi podatki. Gre torej za
kombinacijo metod in podatkov znotraj razreda, z drugimi besedami razvranju oz. klasifikaciji;
Notranje podatke in procese navzven skrijemo gre torej za kontrolo dostopa do metod in podatkov v
kapsuli, z drugimi besedami za kontrolo uporabe razreda.
Razred class je programska struktura, ki zagotavlja sintakso in semantiko za podporo teh dveh dveh temeljnih
nael enkapsulacije.
Kot primer kreirajmo razred krog, ki vsebuje eno metodo (za izraun ploine kroga) in eno lastnost oz. podatek
(polmer kroga). Deklaracijo novega razreda zanemo z rezervirano besedico class, ki ji sledi ime razreda, nato
pa e telo razreda, zapisano med dvema zavitima oklepajema. V telesu razreda so metode (npr. metoda za
ploino), spremenljivke, ki jim pravimo tudi polja razreda ( npr. polmer kroga) in pa lastnosti (properties) o
lastnostih bo ve zapisanega kasneje.
class krog
{
double Ploscina()
//metoda razreda
{
return Math.PI * polmer * polmer;
}
double polmer;
//polje razreda
}
Tako deklariran razred krog pa nima praktine uporabe, saj nismo upotevali drugega naela enkapsulacije:
dostopnost. Potem, ko smo enkapsulirali metode in polje znotraj razreda, smo pred temeljno odloitvijo, kaj
naj bo javno, kaj pa zasebno. Vse kar smo zapisali med zavita oklepaja v razredu, spada v notranjost razreda,
vse kar pa je pred prvim oklepajem in za zadnjim oklepajem pa je zunaj razreda. Z besedicama public, private in
protected pa lahko kontroliramo, katere metode in polja bodo dostopna tudi od zunaj:
Programiranje 1 VS Informatika
C# . NET
123
Metoda ali polje je miljeno kot privatno (private), kadar je dostopno le znotraj razreda. Tako polje oz.
metodo deklariramo tako, da pred tipom metode oz. polja postavimo besedico private.
Metoda ali polje je miljeno kot javno (public), kadar je dostopno tako znotraj, kot tudi izven razreda.
Tako polje oz. metodo deklariramo tako, da pred tipom metode oz. polja postavimo besedico public..
Metoda ali polje je miljeno kot zaiteno (protected), kadar je vidno le znotraj razreda, ali pa v
podedovanih (izpeljanih) razredih.
Deklaracijo naega razreda krog sedaj napiimo e enkrat. Tokrat bomo metodo Ploscina deklarirali kot javno
metodo, polje polmer pa kot privatno polje. Metodo Ploscina bomo v tem primeru lahko poklicali oz. uporabili
tudi izven razreda, neposrednega dostopa do polja polmer pa ne bomo imeli.
class Krog
{
public double Ploscina()
//javna metoda razreda
{
return Math.PI * polmer * polmer;
}
private double polmer;
//zasebno polje razreda
}
e metode ali polja ne deklariramo kot public ali pa private, bo privzeto, da je metoda oz. polje private.
Seveda pa velja, da e so vse metode in polja znotraj razreda privatne, razred nima praktine uporabe.
e hoemo razred, ki smo ga definirali tudi uporabiti, moramo kreirati novo spremenljivko tega tipa, oz. kot
temu pravimo v svetu objektnega programiranje, kreirati moramo novo instanco (primerek) razreda, ki ji
pravimo tudi objekt. Novo spremenljivko tipa Krog lahko deklariramo tako kot vsako drugo spremenljivko.
Naredimo primerjavo med kreiranjem in inicializacijo spremenljivk osnovnih (primitivnih) podatkovnih tipov in
spremenljivk izpeljanih iz razredov (objektov). Osnovna sintaksa je enaka:
int i;
Krog K
e hoemo uporabiti vrednost katerekoli spremenljivke, moramo biti prepriani, da ta spremenljivka e ima
vrednost.
int i;
//deklaracija spremenljike i, celotevilnega tipa
Console.WriteLine(i); //NAPAKA uporaba neinicilaizirane spremenljivke
Programiranje 1 VS Informatika
C# . NET
124
Krog K = new Krog();/*ustvarili smo nov objekt razreda Krog: pri tem smo uporabili privzeti
konstruktor to je metodo Krog(), ki ima enako ime kot razred. */
//Ali pa takole
Krog K;
K = new Krog();
Primer:
class Zgradba//deklaracija razreda Zgradba z dvema javnima poljema. Razred nima nobene metode.
{
public int kvadratura;
public int stanovalcev;
}
static void Main(string[] args)
{
Zgradba hia = new Zgradba(); //nov objekt razreda Zgradba
Zgradba pisarna = new Zgradba(); //nov objekt razreda Zgradba
int kvadraturaPP; // kvadratura na osebo
hia.stanovalcev = 4;
hia.kvadratura = 2500;
pisarna.stanovalcev = 25;
pisarna.kvadratura = 4200;
kvadraturaPP = hia.kvadratura / hia.stanovalcev;
Console.WriteLine("Hia ima:\n " +
hia.stanovalcev + " stanovalcev\n " +
hia.kvadratura + " skupna kvadratura\n
kvadraturaPP + " kvadratura na osebo");
" +
Console.WriteLine();
kvadraturaPP = pisarna.kvadratura / pisarna.stanovalcev;
Console.WriteLine("Pisarna ima:\n " +
pisarna.stanovalcev + " stanovalcev\n " +
pisarna.kvadratura + " skupna kvadratura\n
kvadraturaPP + " kvadratura na osebo");
" +
Vaja:
/*Kreirajmo razred oseba s tirimi polji (ime, priimek, letnik in viina), ter dvema metodama:
metodo za prirejanje podatkov posameznim poljem in metodo za izpis podatkov*/
class Oseba
{
//razred ima tiri zasebna polja
private string ime;
private string priimek;
private int letnik;
private int visina;
//razred ima tudi dve javni metodi
public void VpisiOsebo(string ime,string priimek,int letnik,int visina)
{
//ker imajo parametri metode enako ime kot polja razreda, smo za dostop do polj razreda
//uporabili rezervirano besedo this - ta pomeni referenco na konkreten primerek razreda
//(objekt), oz. referenco na polje konkretnega objekta
this.ime = ime;
this.priimek = priimek;
this. letnik = letnik;
this.visina = visina;
}
public void IzpisiOsebo()
{
Programiranje 1 VS Informatika
C# . NET
125
Vaja:
/*Kreirajmo razred avto s tirimi zasebnimi polji (znamka, model, najvecjahitrost in teza),
ter dvema javnima metodama: metodo za inicializacijo (vnos) polj tega razreda, ter javno
metodo za izpis polj tega razreda. Nato kreirajmo dva objekta, ju inicializirajmo ter izpiimo
njune podatke*/
class avto
{
//zasebna polja razreda avto
private string znamka;
private string model;
private int najvecjahitrost;
private double teza;
public void Inicializacija()//javna metoda za vnos podatkov o konkretnem avtomobilu
{
Console.Write("\nZnamka: ");
znamka = Console.ReadLine();
Console.Write("\nModel: ");
model = Console.ReadLine();
Console.Write("\nNajveja hitrost: ");
najvecjahitrost = Convert.ToInt32(Console.ReadLine());
Console.Write("\nTea vozila: ");
teza = Convert.ToDouble(Console.ReadLine());
}
public void IzpisPodatkov()//javna metoda za izpis podatkov o konkretnem avtomobilu
{
Console.WriteLine("\nIzpis podatkov o vozilu:\n");
Console.WriteLine("Znamka: "+znamka
+"\nModel: "+model
+"\nNajveja hitrost: "+najvecjahitrost
+"\ntea vozila: "+teza);
}
}
static void Main(string[] args)
{
avto mojavto=new avto(); //nov objekt tipa avto (nova instanca razreda)
mojavto.Inicializacija(); //klic metode za inicializac.(vnos) podatkov za konkreten avto
mojavto.IzpisPodatkov(); //klic metode za izpis podatkov o avtomobilu
//kreiramo e drugi objekt, ga inicializiramo in izpiimo e njegove podatke
avto prijateljevavto = new avto();
prijateljevavto.Inicializacija();
prijateljevavto.IzpisPodatkov();
}
Vaja:
/*Kreirajmo razred Prodajalec, ki bo imel zasebno polje zneski (tabela 12 tevil tipa double),
ter javne metode za inicializacijo te tabele: metodo za doloanje prodaje za posamezen mesec,
metodo za izraun celoletne prodaje in metodo za izpis celoletne prodaje*/
class Prodajalec
{
private double[] zneski;
//zasebna tabela ki hrani mesene zneske prodaje
public void inicializacija() //metoda ki inicializira tabelo prodaje
{
Programiranje 1 VS Informatika
C# . NET
126
Vaja:
/*Napiimo razred mojstring, v katerem bomo napisali nekaj javnih metod za delo s stringi, ki
naj pomenijo alternativo obstojeim metodam npr. Length, Replace, ToUpper, ...*/
class mojstring
{
private string stavek; //zasebno polje razreda mojstring
public void DolociStavek(string st) //metoda za inicializacijo polja stavek
{
stavek = st;
}
public int dolzina()//metoda ki vrne tevilo znakov v stringu
{
return stavek.Length;
}
//metoda za zamenjavo doloenih znakov v stringu z novimi znaki
public void ZamenjajZnak(string stari, string novi)
{
stavek = stavek.Replace(stari, novi);
}
public string IzpisStavka()
{
return stavek;
}
public void VelikeCrke()
{
stavek = stavek.ToUpper();
}
}
static void Main(string[] args)
{
mojstring st=new mojstring();
st.DolociStavek("Razred mojstring: metodam za delo s stringi smo priredili slovenska
imena!");
Console.WriteLine("\nV stavku:\n\n"+st.IzpisStavka()+"\n\nje "+st.dolzina()+" znakov!");
st.ZamenjajZnak(" ", "X");//presledke nadomestimo z znakom X
Programiranje 1 VS Informatika
C# . NET
127
Console.WriteLine(st.IzpisStavka());
st.ZamenjajZnak("X"," ");//vse znake "X" nadomestimo s presledki
st.VelikeCrke(); //vse rke v stringu spremenimo v velike rke
Console.WriteLine(st.IzpisStavka());
}
Naloge:
Napii razred Kosarka, za spremljanje koarkake tekme. Voditi mora tevilo prekrkov za vsakega
tekmovalca (10 igralcev), tevilo doseenih tok (posebej 1 toka, 2 toki in 3 toke), ter metodo za
izpis statistike tekme. Doseganje koev in prekrkov realiziraj preko metode zadelProstiMet(),
zadelZa2Tocki, zadelZa3Tocke in prekrsek.
Sestavi razred, ki bo v svoja polja lahko shranil ulico, tevilko nepreminine ter vrsto nepreminine.
Ustvari poljuben objekt, ga inicializiraj in ustvari izpis, ki naj zgleda priblino takole: Na naslovu
Cankarjeva ulica 32, Kranj je blok.
Konstruktor
Konstruktor je metoda razreda, ki se uporablja za kreiranje novega primerka (instance) razreda. Njegovo ime je
vedno enako kot je ime njegovega razreda. Namen konstruktorja pa je, da poskrbi za inicializacijo polj novo
kreiranega objekta. e konstruktorja ne napiemo sami, ga avtomatino za nas skreira prevajalnik. Z drugimi
besedami, originalni razred Krog, za katerega smo zgoraj napisali eno samo metodi in eno polje, v resnici
vsebuje e eno metodo: to je nevidni konstruktor, ki poskrbi za inicializacijo polja polmer. Ta metoda je povsem
enaka, kot e bi napisali celoten razred takole:
class Krog
{
public Krog()
{
polmer = 0.0;
}
public double Ploscina()
{
return Math.PI * polmer * polmer;
}
private double polmer;
}
Konstruktor, ki ga avtomatino generira prevajalnik, je vedno public, nima nobenega tipa (niti void), nima
argumentov, vrednosti numerinih polj postavi na 0, polja tipa bool postavi na false, vsem referennim poljem
(spremenljivkam) pa priredi vrednost null.
Ko je nov objekt inicializiran, lahko dostopamo do njegovih polj in uporabljamo njegove metode. Do javnih
(public) polj (lastnosti razreda) in javnih metod dostopamo s pomojo operatorja pika, tako kot pri strukturah.
Krog K = new Krog();
Console.WriteLine(K.Ploscina()); /*Izpis bo seveda enak 0, ker je privzeti konstruktor polju
polmer avtomatino dodelil vrednost 0!*/
Primer:
/*Kreiraj razred Pravokotnik z dvema poljema (dolina in viina pravokotnika) in dvema
metodama (metoda za izraun ploine in metoda za izraun obsega pravokotnika. Nato ustvari
nov objekt tipa Pravokotnik, doloi stranice pravokotnika in s pomojo metod razreda
Pravokotnik izraunaj njegovo ploino in obseg*/
public class Pravokotnik
{
Programiranje 1 VS Informatika
C# . NET
128
//deklariramo polja; polja bodo javna (public), da bomo imeli do njih dostop izven razreda
public int dolzina,visina; //polji (lastnosti) razreda sta stranici pravokotnika
public Pravokotnik()
//konstruktor (na konstruktor je enak privzetemu konstruktorju!)
{
dolzina=0;
visina=0;
}
public double ploscina()
//metoda, ki izrauna in vrne ploino pravokotnika
{
return (dolzina*visina);
}
public double obseg() //metoda, ki izrauna in vrne obseg pravokotnika
{
return (2*dolzina+2*visina);
}
};
static void Main(string[] args)
{
Pravokotnik P = new Pravokotnik(); //na kopici ustvarimo nov objekt razreda pravokotnik
P.dolzina = 10; //doloimo dolino pravokotnika
P.visina = 8;
//doloimo viino pravokotnika
Console.WriteLine("Ploina pravokotnika: " + P.ploscina()); //klic metode za izraun
//ploine
Console.WriteLine("Obseg pravokotnika: " + P.obseg()); //klic metode za izraun obsega
}
Vaja:
/*Kreiraj razred Kocka z enim privatnim poljem (rob kocke) in s tremi javnimi metodami (metoda
za doloanje robu kocke, metoda za izpis robu kocke in metoda za izraun prostornine kocke.
Nato ustvari nov objekt tipa Kocka, doloi rob kocke in s pomojo metode razreda Kocka
izraunaj njegovo prostornino */
public class Kocka
{
private double rob;
public Kocka() //konstruktor (enak je privzetemu konstruktorju)
{
rob = 0;
}
public void Nastavi_Rob(double x)
//metoda, ki omogoa nastavitev roba kocke
{
rob = x;
}
public double izpis_Roba()
{
return rob;
}
public double prostornina() //metoda, ki izracuna in vrne prostornino kocke
{
return (rob*rob*rob);
}
};
static void Main(string[] args)
{
Kocka K = new Kocka(); //na kopici ustvarimo novo instanco oz. nov objekt razreda Kocka
Random naklj=new Random();
K.Nastavi_Rob(Math.Round(naklj.NextDouble()*10,1)+1); //Rob kocke bo nakljuno realno
//tevilo med 1 in 10
Console.WriteLine("Rob kocke: " + K.izpis_Roba());
Console.WriteLine("Prostornina kocke: " + K. prostornina ());//klic metode za izraun
//prostornine
}
Vaja:
/*Napii razred Kompleksno z dvema poljema (realna in imaginarna), ki naj predstavljata realno
in imaginarno komponento nekega kompleksnega tevila. Napii konstruktor, ki komponentama
priredi doloeni vrednosti. Napii e metodo, ki v primerni obliki izpie poljuben objekt tega
razreda!*/
Programiranje 1 VS Informatika
C# . NET
129
class Kompleksno
{
private int realna, imaginarna; //zasebni polji razreda
public Kompleksno (int real, int imag) // konstruktor, ki poljema priredi celot.vrednosti
{
realna = real;
imaginarna = imag;
}
public void izpisi(string ime) //metoda za izpis
{
Console.WriteLine(ime+" = "+realna + " + " + imaginarna + " * i");
}
}
static void Main(string[] args)
{
Kompleksno alfa=new Kompleksno(1,1); //kreiranje novega objekta tipa Kompleksno
alfa.izpisi("alfa");
Kompleksno beta=new Kompleksno(6,8); //kreiranje novega objekta tipa Kompleksno
alfa.izpisi("beta");
}
Deklarirajmo novo spremenljivko tipa Krog, ji priredimo vrednost novega objekta Krog, nato pa pokliimo
metodo Ploscina:
Krog K = new Krog();
Console.WriteLine(K.Ploscina());
Privzeti konstruktor v vsakem primeru postavi polmer na 0 (ker je polmer private, ga tudi ne moremo
spremeniti), zaradi esar bo tudi ploina objekta Krog vsaki enaka 0. Reitev tega problema je v dejstvu, da je
konstruktor prav tako metoda (sicer metoda posebne vrste), za metode pa velja, da so lahko preobloene
(preobloene metode so metode, ki imajo enako ime, razlikujejo pa se v tevilu ali pa tipu parametrov). Z
drugimi besedami, napiemo lahko svoj lasten konstruktor z vrednostjo polmera kot parametrom. Novi
konstruktor ima seveda enako ime kot razred, ne vraa pa niesar. Razred Krog bo sedaj izgledal takole:
class Krog
{
public Krog(double inicPolmer) //na lasten konstruktor
{
polmer = inicPolmer;
}
public double Ploscina()
{
return Math.PI * polmer * polmer;
}
private double polmer;
}
V primeru, da za nek razred napiemo lasten konstruktor velja, da prevajalnik ne generira privzeti
konstruktor. e pa smo napisali lasten konstruktor, ki sprejme en parameter in bi kljub temu eleli poklicati
Programiranje 1 VS Informatika
C# . NET
130
tudi privzeti konstruktor, ga moramo napisati sami. Pri tem pa moramo biti pozorni na dejstvo, da bodo
vrednosti polj, ki jih v konstruktorju ne bomo inicializirali, e vedno ostala implicitno inicializirana na 0, false ali
pa null.
// kopirni konstruktor
public Cas(Cas obstojeciObjekt)
{
Leto = obstojeciObjekt.Leto;
Mesec = obstojeciObjekt.Mesec;
Dan = obstojeciObjekt.Dan;
}
// zasebna polja razreda Cas
int Leto;
int Mesec;
int Dan;
}
// kreiranje objektov
DateTime trenutniCas = DateTime.Now;
Cas t = new Cas(trenutniCas); // kreiranje
Cas t3 = new Cas(t);
Programiranje 1 VS Informatika
C# . NET
131
Za zagon statinega konstruktorja ne potrebujemo nobenega objekta, saj lahko do njega dostopamo kar preko
imena razreda, npr.:
Console.WriteLine (Sporocilo.Naslov);
//Izpis: C#
Destruktorji
Destruktor je metoda, ki poisti za objektom. Destruktor se torej izvede, ko objekt odmre ( npr. ko se zakljui
nek blok, ali pa se zakljui neka metoda, v kateri je bil objekt ustvarjen) poklie ga torej smetar (Garbage
Collector). Destruktor torej sprosti pomnilniki prostor objekta (prostor, ki ga zasedajo njegovi podatki).
Destruktor ima enako kot konstruktor, enako ime kot razred sam in nima tipa. Ne sprejema argumentov, za
razliko od konstruktorja pa pred destruktorjem stoji e znak '~ '. Med konstruktorjem in destruktorjem pa obstaja
e ena velika razlika. Medtem ko je konstruktorjev doloenega objekta lahko ve, je destruktor vedno samo eden.
Pomembno je tudi to, da destruktorji za razliko od konstruktorjev ne obstajajo v strukturah obstajajo le v
razredih.
class Krog
{
... //deklaracija polj
public Krog() //prvi konstruktor
{
...
}
public Krog(double inicPolmer) //drugi konstruktor
{
...
}
~ Krog() //destruktor
{
...
}
}
Programiranje 1 VS Informatika
C# . NET
132
Dogovor o poimenovanju
Pri poimenovanju javnih polj in metod se skuajmo drati pravila, ki ga imenujemo PascalCase (ker je bilo prvi
uporabljeno v programskem jeziku Pascal). Imena javnih polj in metod naj se zaenjajo z veliko rko (v
zgornjem primeru Ploscina).
Pri poimenovanju zasebnih polj in metod pa se skuajmo drati pravila, ki ga imenujemo camelCase. Imena
zasebnih polj in metod naj se zaenjajo z malo rko (v zgornjem primeru polmer).
Pri tako dogovorjenem poimenovanju je ena sama izjema. Imena razredov naj bi se zaenjala z veliko rko. Ker
pa se mora ime konstruktorja natanno ujemati z imenom razreda, se mora torej tudi ime konstruktorja v
vsakem primeru zaeti z veliko rko, ne glede na to ali je javen ali zaseben.
Primer:
Kot primer napiimo razred Tocka, ki naj ima dve privatni polji x in y, ter dva lastna konstruktorja. Prvi naj bo
brez parametrov in v njegovem telesu le zapiimo stavek, ki bo v oknu izpisal, da je bil ta konstruktor poklican.
Drugi konstruktor pa naj ima dva parametra, s katerima inicializiramo obe polji razreda. V telesu drugega
konstruktorja napiimo stavek, ki izpie vrednosti obeh polj.
class Tocka
{
public Tocka()//Konstruktor brez parametrov
{
Console.WriteLine("Klican je bil privzeti konstruktor!");
}
public Tocka(int x, int y) //Preobloeni konstruktor z dvema parametroma
{
Console.WriteLine("x:{0} , y:{1}", x, y);
}
private int x, y;
}
static void Main(string[] args)
{
Tocka A = new Tocka(); //Klic konstruktorja brez parametrov
Tocka B = new Tocka(600, 800); //KLic konstruktorja z dvema parametroma
}
Vaja:
/*Napiimo razred Tocka, ki nja ima dve zasebni polji (koordinati toke), privzeti
konstruktor, ki obe koordinati postavi na 0, ter konstruktor z dvema parametroma, s katerima
inicializiramo koordinati nove toke. Napiimo e metodo, ki izrauna in vrne razdaljo toke
od neke druge toke*/
class Tocka
{
public Tocka()//lasten privzeti konstruktor
{
x = 0;
y = 0;
Programiranje 1 VS Informatika
C# . NET
133
}
public Tocka(int initX, int initY) //Preobloeni konstruktor z dvema parametroma
{
x = initX;
y = initY;
}
public double RazdaljaOd(Tocka druga) //metoda za izraun razrdalje od poljubne toke
{
int xRazd = x - druga.x;
int yRazd = y - druga.y;
return Math.Sqrt(Math.Pow(xRazd,2) + Math.Pow(yRazd,2));
}
private int x, y;
}
static void Main(string[] args)
{
Tocka A = new Tocka(); //Klic konstruktorja brez parametrov
Tocka B = new Tocka(600, 800); //Klic konstruktorja z dvema parametroma
double razdalja = A.RazdaljaOd(B); //Izraun razdalje obeh tok
Console.WriteLine("Razdalja toke A od toke B je enaka " + razdalja+" enot!");
}
Vaja:
/*Napiimo razred Zaposleni z enim samim zasebnim poljem (dohodek) in dvema konstruktorjema.
Prvi konstruktor naj ima kot parameter letni dodek zaposlenega, drugi pa naj imam dva
paramera: tedenski dohodek in tevilo tednov. Napiimo e metodo za izpis skupnega dohodka*/
public class Zaposleni
{
private double dohodek;
public Zaposleni(int letniDohodek) //konstruktur
{
dohodek = letniDohodek;
}
public Zaposleni(int tedenskiDohodek, int teviloTednov)//preobloeni konstruktur
{
dohodek = tedenskiDohodek * teviloTednov;
}
public double vrniDohodek() //metoda ki vrne vrednost zasebnega polja dohodek
{
return dohodek;
}
}
static void Main(string[] args)
{
Zaposleni Janez = new Zaposleni(20000); //nov objekt, izvede se prvi konstruktor
Zaposleni Tina = new Zaposleni(550, 54); //nov objekt, izvede se drugi (preobloeni)
//konstruktor
Console.WriteLine("Janez ima letni dohodek : " + Janez.vrniDohodek()+" EUR" );
Console.WriteLine("Tina ima letni dohodek : " + Tina.vrniDohodek()+ " EUR");
}
Naloge:
Sestavi razred denarnica, ki bo omogoal naslednje operacije: dvig, vlogo in ugotavljanje stanja.
Zaetna vrednost se naj postavi s konstruktorjem. Ustvari tabelo desetih denarnic z nakljuno mnogo
denarja in jih izpii.
Potrebujemo razred, ki bo hranil podatke o objektih tipa Instrukcije z naslednjimi komponentami: vrsta
intrukcije, tevilo opravljenih ur in ali je intrukcija mona. Razred naj ima tudi metode in sicer:
intrukcija se opravlja, intrukcija se ne opravlja. Z osnovnim konstruktorjem doloi vrednost
(poljubno) vsem komponentam razreda. Z dodatnim konstruktorjem poskrbi za monost nastavitve
Programiranje 1 VS Informatika
C# . NET
134
zaetne vrednosti za vrsto intrukcije, opravljene ure ter ali je intrukcija mona.
Na osnovi razreda Instrukcije napii e testni program, ki bo kreiral in izpisal dva objekta razreda
Instrukcije in sicer tako, da bodo zaetne vrednosti pri prvem objektu nastavljene z osnovnim
konstruktorjem, pri drugem objektu pa z dodatnim konstruktorjem.
Sestavi razred, ki predstavlja osnovo za izdelavo programa, s pomojo katerega bomo pregledovali
rezultate nekega portnega tekmovanja. Sestavi razred Tekmovalec, ki ima naslednje komponente:
startno tevilko, ime, priimek in klub. Vsa polja so tipa string. Napii vsaj dva konstruktorja in pripravi
ustrezne get/set metode za vse te podatke. Z metodo public string tostring() naj se izpiejo podatki o
tekmovalcih (startna tevilka, ime, priimek, klub).
Sestavi razred Pacient, ki ima tri komponente: ime, priimek, krvna_skupina. Komponenti ime in priimek
naj bosta public, krvna_skupina private, vse tri pa tipa string. Napii vsaj dva konstruktorja:
prazen konstruktor, ki vse tri komponente nastavi na "NI PODATKOV",
konstruktor, ki sprejme vse tri podatke in ustrezno nastavi komponente.
Z metodo public string tostring() naj se izpiejo podatki o pacientu (ime, priimek, krvna skupina).
Lastnost (Property)
Polja so znotraj razreda obiajno deklarirana kot zasebna (private). Vrednosti jim priredimo tako, da zapiemo
ustrezen konstruktor (konstruktorje), ali pa da napiemo posebno javno metodo (metode) za prirejanje
vrednosti polj. Ostaja pa e tretji nain, ki je najbolj razirjen za vsako polje lahko definiramo ustrezno lastnost
(property), s pomojo katere dostopamo do posameznega polja, ali pa z njeno pomojo prirejamo
(nastavljamo) vrednosti polja. Lastnosti (properties) v razredih torej uporabljamo za inicializacijo oziroma
dostop do polj razreda (objektov). Lastnost (property) je nekaken krianec med spremenljivko in metodo.
Pomen lastnosti je v tem, da ko jo beremo, ali pa vanjo piemo, se izvede koda, ki jo zapiemo pri tej lastnosti.
Branje in izpis (dostop) vrednosti je znotraj lastnosti realizirana s pomojo rezerviranih besed get in set
imenujemo ju pristopnika (accessors). Accessor get mora vrniti vrednost, ki mora biti istega tipa kot lastnost
(seveda pa mora biti lastnost istega tipa kot polje, kateremu je naemnjena), v accessor-ju set pa s pomojo
implicitnega parametra value lastnosti priredimo (nastavimo) vrednost.
Navzven pa so lastnosti vidne kot spremenljivke, zato lastnosti v izrazih in prirejanjih uporabljamo kot obiajne
spremenljivke.
Primer:
class LastnostDemo
{
int polje;
public LastnostDemo()
{
polje = 0;
}
//zasebno polje
//konstruktor
Programiranje 1 VS Informatika
C# . NET
135
Vaja:
/*Deklarirajmo razred Oseba z dvema poljema (_ime in _priimek) ter javno metodo za
nastavljanje vrednosti obeh polj. Razred naj ima tudi lastnost PolnoIme, za prirejanje in
vraanje polnega imena osebe (imena in priimka). Ustvarimo nov objekt in demonstrirajmo
uporabo lastnosti PolnoIme*/
class Oseba
{
private string _priimek; //zasebno polje razreda Oseba
private string _ime;
//zasebno polje razreda Oseba
public void NastaviIme(string ime, string priimek) //javna metoda razreda
{
_priimek = priimek;
_ime = ime;
}
public string PolnoIme
//javna lastnost razreda
{
get
{
return _ime + " " + _priimek;
}
set
{
string zacasna = value;
string[] imena = zacasna.Split(' '); //Celotno ime razdelimo na posamezne besede
//in jih spravimo tabelo
_ime = imena[0]; //za ime vzamemo prvi string v tabeli
_priimek = imena[imena.Length - 1]; //za priimek vzamemo drugi string v tabeli
}
}
}
static void Main(string[] args)
{
Oseba politik = new Oseba();
politik.NastaviIme("Nelson", "Mandela");
Console.WriteLine("Polno ime osebe je " + politik.PolnoIme);
politik.PolnoIme = "George Walker Bush";
Console.WriteLine("Polno ime osebe je " + politik.PolnoIme);
politik.PolnoIme = "France Preeren";
Console.WriteLine("Polno ime osebe je " + politik.PolnoIme);
Za posamezno polje lahko napiemo le eno lastnost, v kateri s pomojo stavkov get ali set dostopamo oz.
nastavljamo vrednosti posameznega polja.
Besedici get ali set lahko izpustimo in dobimo write-only ali read-only lastnosti.
Primer:
class MojRazred
{
double A = 3;
//zasebno polje
Programiranje 1 VS Informatika
C# . NET
double B = 4;
136
//zasebno polje
Naloge:
Sestavi razred Piramida, ki predstavlja pokonno piramido, ki ima za osnovno ploskev kvadrat. V
razredu hrani podatke o dolini stranice osnovne ploskve in viino piramide. Obe komponenti naj
imata tip dostopa private. Viina in stranica nista nujno celi tevili. Napii vsaj dva konstruktorja:
prazen konstruktor, ki ustvari piramido viine 1 in s stranico osnovne ploskve doline 1
konstruktor, ki sprejme podatka o viini in dolini stranice osnovne ploskve
Napii program, ki ustvari tabelo 50 nakljunih piramid in med njimi poie piramido z
najvejo viino.
Napii get in set metode. V set metodah pazi na smiselnost podatkov (viina in dolina stranice ne
smeta biti negativni,...). Napii tudi metodo tostring, ki vrne niz s smiselnim izpisom podatkov o
piramidi.
2
Sestavi razred, kjer bo v objektih te vrste hranil ime drave, njeno glavno mesto, povrino (v km ) in
tevilo prebivalcev. Pripravi ustrezne get/set metode za vse te podatke in vsaj dva konstruktorja. Ne pozabi
tudi na smiselno metodo tostring.
Sestavi razred Igraa, ki ima tri privatne spremenljivke: tip igrae(tip string), tevilo igra na zalogi(tip int)
ter ceno igrae(tip double).
sestavi prazen konstruktor;
sestavi konstruktor s tremi parametri;
napii ustrezne set in get metode (pazi na smiselne vrednosti spremenljivk);
napii metodo tostring, ki naj smiselno izpie, kateri tip igrae, koliko kosov je na zalogi in kakna
je cena;
dodaj e metodo zalogaIgrac, ki sprejme pozitivno celo tevilo, e se je tevilo igra povealo
(dobava novih) ter negativno celo tevilo e se je tevilo igra zmanjalo (prodane igrae). Temu
primerno spremeni tevilo igra na zalogi in pri tem pazi, da tevilo igra ne pade pod ni;
napii metodo znizanaCena, ki sprejme celo tevilo med 0 in 100 (%), to je za koliko procentov se
bo zniala cena igrae, in nastavi novo ceno igrae;
napii glavni program, ki bo ustvaril pet tipov igra, tri izmed njih znial za 10, 20 in 50% ter dvema
spremenil zalogo.
V kemijskem laboratoriju vekrat preverjamo kislost snovi in jo definiramo s pH vrednostjo. Napii razred
Snov, ki bo imel tri komponente: imeSnovi, ion in kislost. Prvi dve sta tipa string, tretja pa int. Ker je kislost
zelo pomemben podatek o snovi, zagotovi, da bo zagotovo pravilen. Zato bo ustrezna spremenljivka imela
privaten dostop. Sestavi tudi ustrezni get in set metodi. Pazi, da bo tudi v konstruktorju s parametri
poskrbel, da ne bo prilo do napane nastavitve. e bo uporabnik podal napano kislost, ustvari objekt,
kjer za prva dva podatka napie, da sta neobstojea, kislino pa pusti tako, kot jo je vnesel uporabnik.
Sestavi tudi konstruktor brez parametrov, ki naredi objekt, ki predstavlja vodo. Kreiraj tabelo snovi in napii
stavke za izpis vseh objektov.
Programiranje 1 VS Informatika
C# . NET
137
Statine metode
Za laje razumevanje pojma statina metoda, si oglejmo metodo Sqrt razreda Math. e pomislimo na to, kako
smo jo v vseh dosedanjih primerih uporabili (poklicali), potem je v teh klicih nekaj udnega. Metodo Sqrt smo
namre vselej poklicali tako, da smo pred njo navedli ime razreda (Math.Sqrt) in ne tako, da bi najprej naredili
nov objekt tipa Math, pa potem nad njim poklicali metodo Sqrt. Kako je to mono?
Pogosto se bomo sreali s primeri, ko metode ne bodo pripadale objektom (instancam) nekega razreda. To so
uporabne metode, ki so tako pomembne, da so neodvisne od kateregakoli objekta. Metoda Sqrt je tipien
primer take metode. e bila metoda Sqrt obiajna metoda objekta izpeljanega iz nekega razreda, potem bi za
njeno uporabo morali najprej kreirati nov objekt tipa Math, npr takole:
Math m = new Math();
double d = m.Sqrt(42.24);
Tak nain uporabe metode pa bi bil neroden. Vrednost, ki jo v tem primeru elimo izraunati in uporabiti, je
namre neodvisna od objekta. Podobno je pri ostalih metodah tega razreda (npr. Sin, Cos, Tan, Log, ). Razred
Math prav tako vsebuje polje PI (iracionalno tevilo Pi), za katerega uporabo bi potemtakem prav tako
potrebovali nov objekt. Reitev je v t.i. statinih poljih oz.metodah.
V C# morajo biti vse metode deklarirane znotraj razreda. Kadar pa je metoda ali pa polje deklarirano kot
statino (static), lahko tako metodo ali pa polje uporabimo tako, da pred imenom polja oz. metode navedemo
ime razreda. Metoda Sqrt (in seveda tudi druge metode razreda Math) je tako znotraj razreda Math
deklarirana kot statina, takole:
class Math
{
public static double Sqrt(double d)
{
. . .
}
}
Zapomnimo pa si, da statino metodo ne kliemo tako kot objekt. Kadar definiramo statino metodo, le-ta
nima dostopa do kateregakoli polja definiranega za ta razred. Uporablja lahko le polja, ki so oznaena kot static
(statina polja). Poleg tega, lahko statina metoda klie le tiste metode razreda, ki so prav tako oznaene kot
statine metode. Ne-statine metode lahko, kot vemo e od prej, uporabimo le tako, da najprej kreiramo nov
objekt.
Primer:
Napiimo razred toka in v njem statino metodo, katere naloga je le ta, da vrne string, v katerem so zapisane
osnovni podatki o tem razredu
class Tocka
{
public static string Navodila()//Statina metoda
{
string stavek="Vsaka toka ima dve koordinati/polji: x je abscisa, y je ordinata!";
return stavek;
}
}
//Zato, da pokliemo statino metodo oz. statino polje NE
//Primer klica npr. v glavnem programu
Console.WriteLine(Tocka.Navodila());//Klic statine metode
POTREBUJEMO OBJEKTA!!!
Statina polja
Tako kot obstajajo statine metode, obstajajo tudi statina polja. Vasih je npr. je potrebno, da imajo vsi objekti
doloenega razreda dostop do istega polja. To lahko doseemo le tako, da tako polje deklariramo kot statino.
Programiranje 1 VS Informatika
C# . NET
138
class Test
{
public const double Konstanta = 20;//Statino polje
}
//Zato, da pokliemo statino metodo oz. statino polje NE POTREBUJEMO OBJEKTA!!!
Console.WriteLine(Test.Konstanta);//klic statinega polja
Vaja:
class Nekaj
{
static int stevilo=0;
public Nekaj()
{
stevilo++;
}
//Statino polje
// Konstruktor
//tevilo objektov se je povealo
za a
za b
za c
za d
Polje razreda je lahko statino a se njegova vrednost ne more spremeniti: pri deklaraciji takega statinega polja
zapiemo besedico const (const = Constant konstanta). Besedica static pri deklaraciji konstantnega polja NI
potrebna, pa je polje e vedno statino. Konstantno polje je torej avtomatino statino in je tako dostopno
preko imena razreda in ne preko imena objekta! Vrednost statinega polja se NE da spremeniti. Tako je npr.
deklarirana konstanta PI razreda Math.
Primer:
class Test
{
public static double kons1 = 3.14; //Statino polje
public const double kons = 3.1416; //Konstantno polje je avtomatino tudi statino
. . .
Programiranje 1 VS Informatika
C# . NET
139
}
//Zato, da pokliemo statino polje NE POTREBUJEMO OBJEKTA!!!
Console.WriteLine(Test.kons1);//klic statinega polja
Console.WriteLine(Test.kons);//klic konstantnega statinega polja
Test.kons1= Test.kons1 + 1; //OK -> Statino polje LAHKO spremenimo
Test.kons= Test.kons + 1; //NAPAKA -> Konstantnega polja ne moremo spremeniti
Sintaksa, ki jo uporabimo za deklaracijo, s katero elimo povedati, da razred podeduje nek drug razred, je takale:
class IzpeljaniRazred : BaziniRazred
{
. . .
}
Izpeljani razred deduje od bazinega razreda. Za razliko od C++, lahko razred v C# deduje najve en razred in ni
mono dedovanje dveh ali ve razredov. Seveda pa je lahko razred, ki podeduje nek bazini razred, zopet
podedovan v e bolj kompleksen razred.
Primer:
Radi bi napisali razred, s katerim bi lahko predstavili toko v dvodimenzionalnem koordinatnem sistemu. Razred
poimenujmo Tocka:
class Tocka //bazini razred
{
public Tocka(int x, int y)
{
//telo konstruktorja
}
//telo razreda Tocka
}
//konstruktor
Sedaj lahko definiramo razred za tridimenzionalno toko z imenom Tocka3D, s katerim bomo lahko delali
objekte, ki bodo predstavljali toke v tridimenzionalnem koordinatnem sistemu in po potrebi dodamo e
dodatne metode:
class Tocka3D : Tocka //razred Tocka3D podeduje razred Tocka
{
//telo razreda Tocka3D tukaj zapiemo e dodatne metode tega razreda!
Programiranje 1 VS Informatika
C# . NET
140
Vsi razredi imajo vsaj en konstruktor (e ga ne napiemo sami, nam prevajalnik zgenerira privzeti konstruktor).
Izpeljani razred avtomatino vsebuje vsa polja bazinega razreda, a ta polja je potrebno ob kreiranju novega
objekta inicializirati. Zaradi tega mora konstruktor v izpeljanem razredu poklicati konstruktor svojega bazinega
razreda. V ta namen se uporablja rezervirana besedica base:
class Tocka3D : Tocka ////razred Tocka3D podeduje razred Tocka
{
public Toca3D(int z)
:base(x,y) //klic bazinega konstruktorja Tocka(x,y)
{
//telo konstruktorja Tocka3D
}
//telo razreda Tocka3D
}
Poglejmo e, kako lahko kreiramo objekte iz izpeljanih razredov. Kot primer vzemimo zgornji razred Tocka in
iz njega izpeljani razred Tocka3D.
class Tocka //bazini razred
{
//telo razreda Tocka
}
class Tocka3D: Tocka //razred Tocka3D podeduje razred Tocka
{
//telo razreda Tocka3D
}
- razlini tipi
Programiranje 1 VS Informatika
C# . NET
141
Nove metode
Razredi lahko vsebujejo ve ali manj metod in slej ko prej se lahko zgodi, da se pri dedovanju v izpeljanih
razredih ime metode ponovi v izpeljanem razredu torej napiemo metodo, katere ime, tevilo in tipi parametrov
se ujemajo z metodo bazinega razreda. Pri prevajanju bomo zato o tem dobili ustrezno opozorilo - warning.
Metoda v izpeljanem razredu namre v tem primeru prekrije metodo bazinega razreda. e npr. napiemo razred
Tocka in nato iz njega izpeljemo razred Tocka3D,
class Tocka
//bazni razred
{
private int x, y; //polji razreda Tocka
public void Izpis() //metoda za izpis koordinat razreda Tocka
{
Console.WriteLine("Koordinate toke:\nx = " + x + "\ny = " + y);
}
}
class Tocka3D : Tocka
{
private int z;
nam bo prevajalnik zgeneriral opozorilo, s katerim nas obvesti, da metoda Tocka3D.Izpis prekrije metodo
Tocka.Izpis:
Program se bo sicer prevedel in tudi zagnal, a opozorilo moramo vzeti resno. e namre napiemo razred, ki bo
podedoval razred Tocka3D, bo uporabnik morda priakoval, da se bo pri klicu metode Izpis pognala metoda
bazinega razreda, a v naem primeru se bo zagnala metoda razreda Tocka3D. Problem seveda lahko reimo
tako, da metodo Izpis v izpeljanem razredu preimenujemo (npr. Izpis1), e bolja reitev pa je ta, da v
izpeljanem razredu eksplicitno povemo, da gre za NOVO metodo to storimo z uporabo operatorja new.
class Tocka
//bazni razred
{
private int x, y; //polji razreda Tocka
public void Izpis() //metoda za izpis koordinat razreda Tocka
{
Console.WriteLine("Koordinate toke:\nx = " + x + "\ny = " + y);
}
}
class Tocka3D : Tocka
{
private int z;
Vaja:
Programiranje 1 VS Informatika
metodo Izpis
C# . NET
142
/*Napii razred krog z zasebnim poljem polmer in lastnostmi Premer, Obseg in Kvadratura. Iz
razreda nato izpelji razred Krogla, dodaj razredu lastno metodo Kvadratura in novo metodo
Volumen*/
class Krog //Bazini razred
{
private double polmer;//zasebno polje razreda Krog
public double Polmer //lastnost za dostop do polja polmer
{
get
{ if (polmer < 0)
return 0.00;
else
return polmer;
}
set { polmer = value;}
}
public double Premer //lastnost, ki vrne premer kroga
{
get { return Polmer * 2; }
}
public double Obseg //lastnost, ki vrne obseg kroga
{
get { return Premer * Math.PI; }
}
public double Kvadratura //lastnost, ki vrne ploino kroga
{
get { return Math.PI*Math.Pow(Polmer,2); }
}
}
/*Kreirajmo razred Krogla ki naj podeduje razred Krog. Razred Krogla bo podedoval polje
polmer, podedoval bo lastnosti Premer in Obseg, imel bo SVOJO lastnost za izraun kvadrature,
poleg tega pa e novo lastnost za izraun prostornine krogle */
class Krogla : Krog
{
new public double Kvadratura //z operatorjem new smo oznaili, da ima razred krog SVOJO
//lastno lastnost kvadratuta
{
get { return 4 * Math.PI*Math.Pow(Polmer,2); }
}
public double Volumen //nova lastnost razreda Krogla
{
get { return 4 * Math.PI * Math.Pow(Polmer,2) / 3; }
}
}
//glavni program
static void Main()
{
Krog c = new Krog();//nov objekt razreda Krog
c.Polmer = 25.55;
Console.WriteLine("Karakteristike kroga");
Console.WriteLine("Polmer : {0}", c.Polmer);
Console.WriteLine("Premer : {0}", c.Premer);
Console.WriteLine("Obseg
: {0,-10:F2}", c.Obseg);
Console.WriteLine("Ploina: {0,-10:F2}", c.Kvadratura);
Krogla s = new Krogla();//nov objekt razreda Krogla
s.Polmer = 25.55;
Console.WriteLine("\nKarakteristike krogle");
Console.WriteLine("Polmer
: {0}", s.Polmer);
Console.WriteLine("Premer
: {0}", s.Premer);
Console.WriteLine("Obseg
: {0,-10:F2}", s.Obseg);
Console.WriteLine("Povrina
: {0,-10:F2}", s.Kvadratura);
Console.WriteLine("Prostornina: {0,-10:F2}\n", s.Volumen);
}
Programiranje 1 VS Informatika
C# . NET
143
Virtualne metode
Pogosto elimo metodo, ki smo je napisali v bazinem razredu, v vijih (izpeljanih) razredih skriti in napisati
novo metodo, ki pa bo imela enako ime in enake parametre. Eden izmed nainov je uporaba operatorja new za
tako metodo, drug nain pa je z uporabo rezervirane besede virtual. Metodo, za katero elimo e v bazinem
razredu oznaiti, da jo bomo lahko v nadrejenih razredih nadomestili z novo metodo (jo prekriti), oznaimo kot
virtualno (virtual), npr.:
//virtualna metoda v bazinem razredu v izpeljanih razredih bo lahko prekrita(override)
public virtual void Koordinate()
{...}
V nadrejenem razredu moramo v takem primeru pri metodi z enakim imenom uporabiti rezervirano besedico
override, s katero povemo, da bo ta metoda prekrila/prepisala bazino metodo z enakim imenom in enakimi
parametri.
//izpeljani razred besedica override pomeni, da smo s to metodo prekrili bazino metodo
public override void Koordinate()
{ ...}
Loiti pa moramo razliko med tem, ali neka metoda prepie bazino metodo (override) ali pa jo skrije.
Prepisovanje metode (overriding) je mehanizem, kako izvesti drugo, novo implementacijo iste metode
virtualne in override metode so si v tem primeru sorodne, saj se priakuje, da bodo opravljale enako nalogo, a
nad razlinimi objekti (izpeljanimi iz bazinih razredov, ali pa iz podedovanih razredov). Skrivanje metode
(hiding) pa pomeni, da elimo neko metodo nadomestiti z drugo metode v tem primeru niso povezane in
lahko opravljajo povsem razline naloge.
Primer:
Naslednji primer prikazuje zapis virtualne metode Koordinate() v bazinem razredu in override metode
Koordinate() v izpeljanem razredu.
class Tocka
//bazini razred
{
private int x, y;
//polji razreda Tocka
//metoda Koordinate je virtualna, kar pomeni, da jo lahko prepiemo (override)
public virtual void Koordinate() //metoda za izpis koordinat razreda Tocka
{
Console.WriteLine( "Koordinate toke:\nx = "+x + "\ny = " + y);
}
}
class Tocka3D : Tocka
{
private int z;
//Metoda Koordinate je oznaena kot override - prepie istoimensko metodo razreda Tocka
public override void Koordinate()
{
base.Koordinate(); //klic bazine metode Koordinate razreda Tocka
Console.Write("z = "+z+"\n");
}
}
Programiranje 1 VS Informatika
C# . NET
144
Obe metodi morata imeti enak dostop. e je npr. virtualna metoda oznaena kot javna (public), mora
biti javna tudi metoda override;
Prepiemo (prekrijemo/povozimo) lahko le virtualno metodo. e metoda ni oznaena kot virtualna in
bomo v nadrejenem razredu skuali narediti override, bomo dobili obvestilo o napaki;
e v nadrejenem razredu ne bomo uporabili besedice override, bazina metoda ne bo prekrita. To pa
hkrati pomeni, da se bo tudi v izpeljanem razredu izvajala metoda bazinega razreda in ne tista, ki smo
napisali v izpeljanem razredu;
e neko metodo oznaimo kot override, jo lahko v nadrejenih razredih ponovno prekrijemo z novo
metodo.
Vaja:
Razred Tocka in razred Tocka3D, ki je izpeljan iz razreda Tocka sta implementirana v naslednjem primeru:
class Tocka
//bazni razred
{
private int x, y;
Vaja:
/*Napiimo razred krog z zasebnim poljem polmer in virtualno metodo ploscina, nato pa e
razred kolobar. Razred kolobar naj deduje razred krog, dodano naj ima e eno zasebno polje
notranjiPolmer in svojo lastno(override) metodo polina*/
class krog
//bazni razred
{
private int polmer;
//polje razreda krog
//metoda ploscina je virtualna, kar pomeni, da jo lahko preobloimo (override)
public virtual double ploscina()
{
return Math.PI * polmer * polmer;
Programiranje 1 VS Informatika
C# . NET
145
}
public int Polmer //lastnost(property) razreda krog, za dostop in inic. polja polmer
{
get
{
return polmer;
}
set
{
polmer = value;
}
}
}
class kolobar : krog
//razred kolobar podeduje razred krog
{
//ker kolobar deduje krog, e pozna polje polmer
private int notranjiPolmer; //dodatno polje razreda kolobar
//metoda ploscina prepie istoimensko metodo bazinega razreda krog
public override double ploscina()
{
return Math.PI * (Polmer * Polmer - notranjiPolmer*notranjiPolmer);
}
//ker kolobar deduje krog, e pozna njegovo lastnost Polmer
//dodatna lastnost (property) razreda kolobar, za dostop in inic. polja notranjiPolmer
public int NotranjiPolmer
{
get
{
return notranjiPolmer;
}
set
{
notranjiPolmer = value;
}
}
}
static void Main(string[] args)
{
Random naklj = new Random();
krog k=new krog();
k.Polmer = naklj.Next(1, 10);
Vaja:
//Deklarirajmo razred Oseba, nato pa razred Kmetovalec, ki naj podeduje razred Oseba. Razred
Oseba naj ima polje ime, razred Kmetovalec pa e dodatno polje velikostPosesti. Za oba razreda
napiimo tudi konstruktor in virtualno metodo Tostring za izpis podatkov o posameznem
objektu!*/
//glavni program
static void Main(string[] args)
{
ArrayList osebe = new ArrayList();
//zbirka oseb
Programiranje 1 VS Informatika
C# . NET
146
}
public class Oseba
{
public string ime;
public Oseba(string ime)
{
this.ime = ime;
}
//bazini razred
//bazino polje
//bazini konstruktor
}
public class Kmetovalec : Oseba //razred Kmetovalec deduje razred Oseba
{
int velikostPosesti; //dodatno polje razreda Kmetovalec
public Kmetovalec(string ime, int velikostPosesti) //konstruktor razreda Kmetovalec
: base(ime)
//podeduje bazino polje ime
{
this.velikostPosesti = velikostPosesti;
}
public override string Tostring() //metoda Tostring prekrije bazino metodo Tostring
{
return base.Tostring() + "; Kvadratnih metorv = " +
velikostPosesti.Tostring();
}
}
Naloge:
Napii razred Kocka tako, da bo izpeljan iz razreda Kvadrat. Razreda naj poleg svojih podatkov
vsebujeta e privzeti konstruktor, metode za postavitev vrednosti podatkov in metode za izraun
povrine, obsega in volumna.
Polimorfizem - mnogolinost
Programiranje 1 VS Informatika
C# . NET
147
virtualno metodo
Ker smo metodo Slika definirali kot virtualno, smo s tem napovedali, da bodo izpeljani objekti lahko
uporabljali svojo (prekrivno oz. override) metodo Slika, ki pa bo imela enako ime.
Razred OsnovniRazred bo na temeljni razred, iz katerega bomo tvorili izpeljane razrede in v njih tvorili
nove objekte. Ker je metoda Slika virtualna to pomeni, da lahko v izpeljanih razredih to metodo prekrijemo
(override) z metodo, ki bo imela enako ime a drugaen pomen (drugano vsebino).
Napiimo sedaj e tri razrede, ki naj bodo izpeljani iz razreda OsnovniRazred in ki imajo svojo metodo
Slika. Pred tipom takih metod mora stati besedice override, ki oznauje, da se bodo objekti izpeljani iz teh
razredov na to metodo odzivali vsak na svoj nain. Osnovni pogoj pa je, da imajo take override metode enako
raven zaite (npr. vse so public) , enako ime in enake parametre kot jih ima osnovna virtualna metoda v
bazinem razredu.
public class Crta : OsnovniRazred //Crta je razred, ki podeduje razred OsnovniRazred
{
public override void Slika()
//preobloena metoda razreda Crta
{
Console.WriteLine("rta.");
//Telo override metode je seveda lahko drugano!!!
}
}
public class Krog : OsnovniRazred //Tudi Krog je razred, ki podeduje razred OsnovniRazred
{
public override void Slika()
{
Console.WriteLine ("Krog."); //Telo override metode je seveda lahko drugano!!!
}
}
public class Kvadrat: OsnovniRazred //Tudi Kvadrat je razred, ki podeduje razred OsnovniRazred
{
public override void Slika()
//Telo override metode je seveda lahko drugano!!!
{
Console.WriteLine ("Kvadrat.");
}
}
Poglejmo sedaj, kako bi te tiri razrede sedaj uporabili in na primeru izpeljanih objektov prikazali princip
polimorfizma. V ta namen kreirajmo tabelo objektov. Ime tabele je dObj, tabela pa naj bo inicializirana tako,
da so v njej lahko tiri objekti tipa OsnovniRazred.
Programiranje 1 VS Informatika
C# . NET
148
Ker so razredi Crta, Krog in Kvadrat izpeljani iz bazinega razreda OsnovniRazred, jih lahko
priredimo isti tabeli dObj. e te zmonosti ne bi bilo, bi morali za vsak nov objekt, izpeljan iz kateregakoli od
teh tirih razredov, kreirati svojo tabelo. Dedovanje pa nam omogoa, da se vsak od izpeljanih objektov obnaa
tako kot njegov bazini razred. Naslednjo kodo lahko zapiemo npr. v dogodek Click nekega gumba, ali pa neko
opcijo menija.
dObj[0]
dObj[1]
dObj[2]
dObj[3]
=
=
=
=
new
new
new
new
Crta();
//konstruktor
Krog();
//konstruktor
Kvadrat();
//konstruktor
OsnovniRazred();//konstruktor
objekta
objekta
objekta
objekta
dObj[0]
dObj[1]
dObj[2]
dObj[3]
Ko je tabela inicializirana, lahko npr. s foreach zanko pregledamo vsakega od objektov v tabeli. Zaradi naela
polimorfizma se v zagnanem programu vsak objekt obnaa po svoje, pa odvisno od tega, iz katerega razreda je
bil izpeljan. Ker smo v izpeljanih razredih prepisali virtualno metodo Slika , se ta metoda v izpeljanih objektih
izvaja razlino, pa glede na njeno definicijo v izpeljanih razredih. Pri vsakem prehodu zanke bomo tako dobili
drugano sporoilno okno.
Programiranje 1 VS Informatika
C# . NET
149
Objektno programiranje
Objekti
Objekt je skupek podatkov, s katerim elimo upravljati kot s celoto.
Ima
Metode
Vsak objekt pripada nekemu razredu. e pripada objekt x razredu R, potem pravimo
tudi da je x objekt tipa R.
Znani objekti
Nekaj primerov objektov iz standardnih knjinic jezika C# :
Podatke
Seveda pa so objekti uporabni predvsem zato, ker lahko programer definira nove razrede in objekte.
Objekti
stanja:
Programiranje 1 VS Informatika
C# . NET
150
Ulomek:
Primeri objektov
Datum
Vrni mesec
Vrni tevilo dni med dvema datumoma
Naslednji dan
Prejnji dan
Lepo izpii
Je leto prestopno
Dan v tednu na doloen datum
...
Avto
Podatki
tehnine znailnosti:
Programiranje 1 VS Informatika
C# . NET
151
najvecjaHitrost (v km/h),
velikostRezervoarja (v litrih)
povprenaPoraba (v litrih/100 km).
"Obnaanje"
Primer problema
Napisati morate program, ki bo nadzoroval delovanje dvigal
Objekt Dvigalo
Podatki (stanje) objekta:
Primer problema
Vodimo skladie kontejnerjev
Programiranje 1 VS Informatika
C# . NET
152
Razred Kontejner
Tabela kontejnerjev
Posamezni kontejner
Nov razred
Mere
Zapolnjenost (v %)
Vsebino
Programiranje v C#
Sestavljanje razredov
Programiranje 1 VS Informatika
C# . NET
153
Zaetek
Objekti
Objekt je kakrenkoli skupek podatkov, s katerimi elimo
upravljati.
Osnovni pristop objektnega programiranja
obj.KolikoJeIQ()
Programiranje 1 VS Informatika
C# . NET
154
Npr.:
ef ugotovi, da bi bilo smiselno, da v vaih programih pri datumu hranite e as. Ampak stvari naj bi
naredili tako, da obstojei programi ne bi bili prizadeti (beri, da bi delali e naprej)
e je razred "rna" katla, lahko naredimo spremembe tako, da ne bo "staro" prizadeto
Verjetno je zgradba menjalnika danes bistveno drugana, kot je bila pred 30 leti
A kar se oferja (starega ;-) ) tie, se ni ni spremenilo s to rno katlo (menjalnikom) upravlja e vedno
na enak nain kot pred 30 leti
e se bodo v C# 2013 odloili, da razred Random spemenijo (spremenijo notranjost "rne katle"), a bomo e vedno imeli
metodo Next(a, b), se za programerja ne bo ni spremenilo, eprav bo metoda Next morda "znotraj" delala drugae!
Od kje razredi?
Veliko vgrajenih (oziroma v standardnih knjinicah) v C#
.NET Framework
C# je .NET jezik ima dostop do vseh razredov, definiranih v knjinicah (zbirkah
razredov) okolja .NET
us).aspx
System, System.IO
Drugi viri
Programiranje 1 VS Informatika
C# . NET
155
using System;
MojR prvi;
new NekiObjekt();
a = new NekiObjekt();
C# . NET
156
Ustvarjanje objektov
Razred je ablona, ki definira spremenljivke in metode skupne vsem objektom iste vrste.
class
Ustvarimo ga z new
Brez tega objekta NE MOREMO uporabiti
NekiObjekt a;
Objekt NE obstaja
a je IME objekta
natanneje
C#in objekti
Razred (class) je opis vrste objekta (nart, kako naj bo objekt videti) opis ideje objekta
Primerek razreda (instanca) konkretni objekt
Ustvarjanje objektov
Ulomek ime = new Ulomek(3, 4);
Reemo:
Toneje
deklaracija
prireditev
Ulomek ime;
ime = new Ulomek(3, 4);
Programiranje 1 VS Informatika
C# . NET
157
Ustvarjanje objektov
Ulomek ime;
ime = new Ulomek(3, 4);
e en zgled
Poglejmo si e en zgled. Denimo, da bi radi napisali program, ki bo prebral nek
ulomek in mu pritel 1/2.
"klasino" se bomo tega lotili takole
Programiranje 1 VS Informatika
C# . NET
158
Programiranje 1 VS Informatika
C# . NET
159
"Objektni" program
Ulomki - objektno
using System;
namespace UlomkiObjektno
{
class Ulomek {
public int stevec;
public int imenovalec;
Ulomki - objektno
Console.Write("tevec ulomka: ");
string beri = Console.ReadLine();
int stevec = int.Parse(beri);
Console.Write("Imenovalec ulomka: ");
beri = Console.ReadLine();
int imenovalec = int.Parse(beri);
Programiranje 1 VS Informatika
C# . NET
160
// "delo"
moj.Pristej(polovica);
// izpis
Console.WriteLine("Nov ulomek je: " + moj.stevec + " / " +
moj.imenovalec);
Primerjava
"klasino"
// "delo"
stevec = stevec + 1;
imenovalec = imenovalec + 2;
objektno
Ulomek
Ampak ulomke smo setevali narobe, po "Janezkovo"!
Saj veste ... Inpektor ree ... Saj se ulomki ne setevajo tako, da se posebej setejeta
tevec in imenovalec ... Uitelj Janezek pa ... Saj vem, ampak tako si laje zapomnijo ...
C# . NET
161
Klasino: preko kode vseh 10 programov in "iemo", kje smo pravzaprav setevali
Objektno: le spremenimo metodo Pristej v razredu Ulomek, nato pa
Objektno programiranje
Problem
Standardna knjinica
Druge knjinice
Nai stari razredi
Zdruevanje podatkov
Denimo, da piemo program, ki bo pomagal upravljati farmo
zajcev
Za vsakega zajca poznamo:
serijsko tevilko
spol
teo
Tabela ni ustrezna
Programiranje 1 VS Informatika
C# . NET
162
"lokalni" razredi
Kot prej (Console Application ...)
namespace PrviOOP {
public class MojR {
private string mojNiz;
public MojR(string nekNiz) {
mojNiz = nekNiz;
}
public void Izpisi(){
Console.WriteLine(mojNiz);
}
}
public class Pozdrav {
public static void Main(string[] arg) {
MojR prvi;
prvi = new MojR("Pozdravljen, moj prvi objekt v C#!");
prvi.Izpisi();
}
}
}
Knjinica razredov
Knjinice razredov
Programiranje 1 VS Informatika
C# . NET
163
Komentarji
// - vrstini komentar
/* ... */ : sploen komentar
/// dokumentacijski komentar
Glej npr:
http://www.softsteel.co.uk/tutorials/cSharp/lesson19.html
http://www.winnershtriangle.com/w/Articles.XMLComments
InCSharp.asp
http://www.csharphelp.com/archives3/archive598.html
Razred Zajec
public class Zajec {
public string serijska;
public bool spol;
public double masa;
}
Prevedemo
Hisa.dll (na zgled: MojiRazredi.dll)
Programiranje 1 VS Informatika
C# . NET
164
Zajec rjavko
ustvarimo z new
new Zajec()
Ustvaril se je konkreten zajec po navodilih za razred Zajec (ta zajec ima torej tri
C# . NET
165
rjavko.spol = true;
rjavko.serijska = BRGH_17_A;
rjavko.masa = 3.2;
Razred Zajec
e konni pogled na naslove
shranimo podatke o posameznem zajcu. Naslov tega prostora za tabelo smo shranili v spremenljivko
tabZ.
V tem trenutku ne obstaja e noben objekt tipa Zajec.
Operator new je nekje ustvaril prostor za objekt tipa Zajec. Naslov tega objekta se je shranil v 0-to
celico tabele, katere naslov je shranjen v spremenljivki tabZ.
Programiranje 1 VS Informatika
C# . NET
166
Povzetek
Definicija razreda
Obiajno v knjinici!
Programiranje 1 VS Informatika
C# . NET
167
Povzetek
Uporaba razreda
Operator .
imeObjekta.elementi
imeObjekta.imeKomponente
mojaSpTipaImeRazreda.starost
Konstruktorji
C# . NET
168
Razred Zajec
public class Zajec {
public String serijska;
public boolean spol;
public double masa;
// konstruktor
public Zajec() {
this.spol = true; // vsem zajcem na
this.masa = 1.0; // in tehtajo 1kg
this.serijska = NEDOLOENO;
}
}
new Zajec()
Ustvaril se je konkreten zajec po navodilih iz konstruktorja
Zajec() (ta zajec ima torej tri podatke z vrednostmi, kot
je predpisano v konstruktorju)
Kaj je this?
this
this
C# . NET
169
this.spol
Lastnost/komponenta spol objekta, ki se ustvarja
Programiranje 1 VS Informatika
C# . NET
170
Konstruktorji
public Zajec() {
}
C# . NET
171
Ve konstruktorjev
Preobteevanje
Je to mono?
Preobteevanje
Overloading
Velja tudi splono, za vse metode
x)
Programiranje 1 VS Informatika
C# . NET
172
Podpisi metod
Podpis metode:
public static int NekaMetoda(double
Podpis: NekaMetoda_double
interno ime
public Zajec(string serijskaStev,
x)
Podpis:
Zajec_String_bool_double
Programiranje 1 VS Informatika
C# . NET
173
Sklicevanje na konstruktorje
public Zajec(string ser, bool sp,
double t) : this(ser)
{
this.spol = sp;
this.masa = t;
}
this
this(
this()
this(<parametri>)
this.
Za dostop do lastnosti
this.serijska
e ni monosti zamenjave, lahko izpustimo
serijska
this.spol = spol;
Obstajala je e DRUGO ime spol
Loiti med spremenljivko spol, ki je parameter in lastnostjo objekta z
imenom spol
spol
= spol;
C# . NET
174
Programiranje 1 VS Informatika
C# . NET
175
Klub - uporaba
using MojaKnjiznica;
public class TestKlub {
public static void Main(string[] args) {
Clan c = b;
c.ime = "Andreja";
Programiranje 1 VS Informatika
C# . NET
176
Zakaj
public class TestKlub {
public static void Main(string[] args) {
Clan a;
a = new Clan();
a.ime = "Janez";
a.priimek = "Starina";
a.letoVpisa = 2000;
a.vpisnaStevilka = "2304";
Clan c;
c = b;
c.ime = "Andreja";
Programiranje 1 VS Informatika
C# . NET
177
Programiranje 1 VS Informatika
C# . NET
178
C# . NET
179
Tega sedaj ni
Popravljeni zgled
public class Clan {
public string ime;
public string priimek;
public int letoVpisa;
public string vpisnaStevilka;
public Clan() {
this.ime = "Ne vem";
this.priimek = "Ne vem";
this.letoVpisa = 0;
this.vpisnaStevilka = "Ne vem";
}
Ni teav!
Poskus testa
Programiranje 1 VS Informatika
C# . NET
180
Programiranje 1 VS Informatika
C# . NET
181
Clan c = b;
c.ime = "Andreja";
...
Programiranje 1 VS Informatika
C# . NET
182
c.ime = "Andreja";
...
Objektne metode
imeObjekta.imeMetode(parametri)
System.Console.WriteLine("To naj se
izpie");
besedilo.Equals(primerjava)
Programiranje 1 VS Informatika
C# . NET
183
Uporaba metode
using MojiRazredi; // knjinica z razredom Clan
public class TestClan{
public static void Main(string[] args) {
Clan a = new Clan("Janez", "Starina", 2000, "2304");
String inicialkeClanaA = a.Inicialke();
Console.Write("Clan a:\n" + a.ime + " " + a.priimek +
" " + a.letoVpisa + " (" + a.vpisnaStevilka +
") ");
Console.WriteLine("ima inicialke: " + inicialkeClanaA);
}
}
Sprememba metode
public class Clan {
public string ime;
Programiranje 1 VS Informatika
C# . NET
184
public Clan() {
ime = "Ne vem";
priimek = "Ne vem";
letoVpisa = 0;
vpisnaStevilka = "Ne vem";
}
public Clan(string i, string p, int l, string v) : this() {
ime = i;
priimek = p;
letoVpisa = l;
vpisnaStevilka = v;
}
public string Inicialke() {
return this.ime[0] + " " + this.priimek[0];
}
}
Vemo, da z
a = b;
kjer sta a in b obe spremenljivki tipa Clan,
v a ne shranimo kopije objekta b, ampak
sedaj a in b oznaujeta isti objekt.
Metoda, ki naredi kopijo objekta.
Programiranje 1 VS Informatika
C# . NET
185
a = b.Kopija();
Programiranje 1 VS Informatika
C# . NET
186
Kopija
public Clan Kopija() {
Clan nov = new Clan();
nov.ime = this.ime;
nov.priimek = this.priimek;
nov.letoVpisa = this.letoVpisa;
nov.vpisnaStevilka =
this.vpisnaStevilka;
return nov;
}
e metoda za izpis
public void Izpis() {
Console.WriteLine("Clan:\n" + this.ime + " " +
this.priimek + " " + this.letoVpisa +
" (" + this.vpisnaStevilka + ")\n");
}
ali pa e
Programiranje 1 VS Informatika
C# . NET
187
Uporaba
public class TestKlub {
public static void Main(string[] args) {
Programiranje 1 VS Informatika
C# . NET
188
Razred Datum
dan (tevilo)
mesec (izbira: tevilo ali pa niz)
Leto (tevilo)
Metode
Konstruktorji
Izpii
Poveaj za 1 dan
Je datum smiselen
Je leto prestopno
Nov datum za toliko in toliko dni pred/za danim datumom
Dan v tednu
...
Programiranje 1 VS Informatika
C# . NET
189
Dodatni konstruktorji
public Datum(int leto) : this() {
this.leto = leto; // this je nujen
} // datum je torej 1.1.leto
public Datum(int d, string m, int l) : this(l)
{ // leto smo e nastavili
this.mesec = m; // this ni nujen
this.dan = d;
} // datum je torej d.m.l (na primer 12.3.2006 ali
Programiranje 1 VS Informatika
C# . NET
190
Prestopno
Programiranje 1 VS Informatika
C# . NET
191
Dodaj en dan
public void PovecajZaEnDan() {
dan = dan + 1;
if (dan < 29) return;
if (dan == 29 && mesec != "februar") return;
if (dan == 29 && mesec == "februar" && this.JePrestopno())
return;
// lahko nehamo, mesec in leto sta ok
string[] meseciPo30 = {"april","junij","september",
"november"};
if (dan == 31) {
if (meseciPo30.IndexOf(mesec) > 0){
mesec = mesec + 1;
if (mesec == 13) {
mesec = 1;
leto++;
}
Programiranje 1 VS Informatika
C# . NET
192
return;
}
// e je 32 dni, je zagotovo
Uporaba razreda
Programiranje 1 VS Informatika
C# . NET
193
using MojiRazredi;
public class JeLetosPrestopnoLeto {
Datum danes = new Datum(5, 3, 2009);
if (danes.jePrestopno()) {
Console.WriteLine("Je prestopno
leto");
} else {
Console.WriteLine("Ni prestopno
leto");
}
}
Imamo
Sprememba razreda
Programiranje 1 VS Informatika
C# . NET
194
public Clan() {
ime = "Ne vem";
priimek = "Ne vem";
datumVpisa = new Datum();
vpisnaStevilka = "Ne vem";
}
Sprememba razreda
public Clan(string i, string p, Datum d, string v) : this() {
ime = i;
priimek = p;
datumVpisa = d;
vpisnaStevilka = v;
}
Programiranje 1 VS Informatika
C# . NET
195
return nov;
}
Sprememba razreda
public string Opis() {
return this.ime + " " + this.priimek + " " +
this.datumVpisa.OpisDat() + " (" + this.vpisnaStevilka + ");
}
}
return false; // leto ni smsielno, ne spremnimo in in vrnemo
false
}
}
Programiranje 1 VS Informatika
C# . NET
196
Sprememba razreda
public Clan(string i, string p, Datum d, string v) : this() {
ime = i;
priimek = p;
datumVpisa = d;
vpisnaStevilka = v;
}
Sprememba razreda
public void Izpis() {
Console.WriteLine("Clan:\n" + this.ime + " " +
this.priimek + " " + this.datumVpisa.OpisDat() +
this.vpisnaStevilka + ")\n");
}
public string Opis() {
Programiranje 1 VS Informatika
" (" +
C# . NET
197
}
return false; // leto ni smiselno, ne spremenimo ni in vrnemo false
}
}
Nain programiranja
if (enClan.letoVpisa >
drugClan.letoVpisa) {
ne deluje ve!
Kako popraviti?
Programiranje 1 VS Informatika
C# . NET
198
e v prvotnem razredu
public class Clan {
public string ime;
public string priimek;
public int letoVpisa;
public string vpisnaStevilka;
Le metodo
Programiranje 1 VS Informatika
C# . NET
199
zamenjamo z
public int VrniLetoVpisa() {
return this.datumVpisa.leto;
}
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
Programiranje 1 VS Informatika
C# . NET
200
Zgled
public class TestClan{
public static void Main(string[] args) {
Clan novClan = new Clan();
novClan.ime = "Katarina";
novClan.letoVpisa = 208;
Dodajmo metodo
Programiranje 1 VS Informatika
C# . NET
201
Uporaba metode
public class TestKlub {
public static void Main(string[] args) {
Clan novClan = new Clan();
novClan.ime = "Katarina";
novClan.letoVpisa = 2007;
novClan.SpremeniLetoVpisa(208);
Programiranje 1 VS Informatika
C# . NET
202
novClan.SpremeniLetoVpisa(2008);
Dostopi do stanj
ime_objekta.stanje
Zakaj je to lahko problem?
z1.masa = -100.10;
Naini dostopa
public
private
protected
internal
public string serijska; private Datum datumRojstva;
private double masa; public int[] tab;
bool spol;
public
Znotraj razreda NI omejitev, vedno (ne glede na
nain dostopa) je moen dostop do komponent.
public
Do lastnosti lahko dostopajo vsi, od kjerkoli (iz katerihkoli
datotek (razredov))
imeObjekta.lastnost
MojObjekt
Programiranje 1 VS Informatika
C# . NET
203
MojObjekt
x = new MojObjekt();
x.javnaLastnost
private
private
// v
razredu MojObjekt
Programiranje 1 VS Informatika
C# . NET
204
Razred Zajec
public class Zajec {
public string serijska; // serijska stevilka zajca
public bool spol; // true = moski, false = zenska
Razred Zajec2
public class Zajec2 {
public string serijska; // serijska stevilka zajca
public bool spol; // true = moski, false = zenska
private
public SpremeniTezo(double x) {
this.masa = x;
}
Dostop do stanj/lastnost
Kako uporabiti:
Programiranje 1 VS Informatika
C# . NET
205
Dostop do stanj/lastnost
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 tee
smiselna!
zajcek.SpremeniTezo(-12.5);
V bistvu isto kot zajcek.masa = -12.5;
A tu bomo lahko PREPREILI postavitev lastnosti objekta v napano stanje!
Programiranje 1 VS Informatika
C# . NET
206
SpremeniTezo
NE
Imata enak podpis (ime + tipi parametrov)
Tip rezultata NI del podpisa!
Metoda je seveda lahko bolj kompleksna denimo vemo, da se tea ne more spremeniti bolj kot za
15%
Programiranje 1 VS Informatika
C# . NET
207
if ((0 < novaTeza) && (novaTeza <= 10) && (sprememba <= 15) ){
masa = novaTeza; // this.masa ... Lahko pa this spustimo!
return true; // sprememba uspela
}
// v nasprotnem primeru NE spremenimo tee
// in javimo, da spremembe nismo naredili
return false;
}
Tea in konstruktor
Seveda je smiselno, da zagotovimo, da je tea ustrezna e ves
as!
Pozor na zaetno stanje: konstruktor!
Pogosto na to pozabimo
Programiranje 1 VS Informatika
C# . NET
208
SpremeniSpol,
SpremeniSerijsko
Kaj pa SpremeniSpol
SpremeniSerijsko
Poizvedba
Dostop do stanj
spremenljivka v izrazu
zajcek.PovejTezo()
Programiranje 1 VS Informatika
C# . NET
209
Programiranje 1 VS Informatika
C# . NET
210
// konstruktor
public Zajec() {
this.spol = true; // vsem zajcem na zaetku doloimo m.
spol
this.masa = 1.0; // in tehtajo 1kg
this.serijska = "NEDOLOENO";
}
public Zajec(string serijskaStev):this() {
this.serijska = serijskaStev;
}
public Zajec(string serijskaStev, bool spol, double
masa):this() {
this.serijska = serijskaStev;
this.SpremeniTezo(masa);
Programiranje 1 VS Informatika
C# . NET
211
this.spol = spol;
}
C# . NET
212
}
public void SpremeniSerijsko(string s) {
this.serijska = s;
}
public bool JeSamec() {
return this.spol;
}
} // Zajec
Ostale metode
C# . NET
Odzivi objektov
"znanje objektov"
213
"niz".IndexOf("i")
nekNiz.ToLower()
mojPriimek.Equals("Lokar")
"nai" razredi
Programiranje 1 VS Informatika
C# . NET
214
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);
Programiranje 1 VS Informatika
C# . NET
215
ToString
Oitno objekte lahko tudi izpiemo
Gre seveda tudi takole
string niz = "Zajec " + zeko + "!";
Torej se tudi objekti "obnaajo" tako kot int, double ... (se torej
pretvorijo v niz)
A s pretvorbo nismo ravno zadovoljni, radi bi kakne bolj
smiselne informacije
V razredu, ki ga definiramo (recimo Zajec) napiemo metodo
ToString
e na doloenem mestu potrebujemo niz, a naletimo na objekt,
se ta metoda poklie avtomatino
Programiranje 1 VS Informatika
C# . NET
216
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);
ToString
Posebnost - override
Programiranje 1 VS Informatika
C# . NET
217
Zaradi "dedovanja"
O tem kasneje
Z dedovanjem smo avtomatino 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() ;
C# . NET
218
Razred Clan
e malo o zajcih
Preden nadaljujemo
e konstruktor
Problemi s konstruktorjem
Programiranje 1 VS Informatika
C# . NET
219
public Zajec() {
this.spol = true;
this.masa = 1.0;
this.serijska = "NEDOLOENO";
this.oce = new Zajec();
this.mama = new Zajec();
}
Problemi s konstruktorjem
Ustavitveni pogoj
A pri konstruktorju brez parametrov ni parametrov, ki bi lahko
doloili ustavitveni pogoj
Kaj storiti
C# . NET
220
obstajati
Razred Avto
Sprogramirajte razred Avto, ki predstavlja avtomobil z njegovimi tehninimi znailnostmi in trenutnim
stanjem.
Razred naj vsebuje sledee attribute:
Poleg atributa stevilka, ki omogoa loevanje posameznih avtomobilov, so tehnine znailnosti opisane z
atributi najvecjaHitrost (v km/h), velikostRezervoarja (v litrih) in povprenaPoraba (v
litrih/100 km). Trenutno stanje avtomobila predstavljajo atributi avtoVzgan (tipa boolean), stevecKm (npr.
234.142 km), trenutnaHitrost (npr. 56.12 km/h) in kolicinaGoriva (npr. 14.325 litrov).
Razred naj vsebuje naslednje metode:
NastaviStevilko(s): nastavi atribut stevilka na s (recimo 1),
VzgiAvto(): nastavi atribut avtoVzgan na true, pri emer se porabi 0.05 litra goriva (e ni zadosti
goriva se avto ne vge)
UgasniAvto(): nastavi atribut avtoVzgan na false, pri emer se lahko avto ugasne le, ko je njegova
hitrost enaka 0.
Vozi(t): vozi t minut s trenutno hitrostjo in vrne koliko poti je v tem asu prevozil. Metoda povzroi
spremembo atributov stevecKm in kolicinaGoriva. e je goriva premalo, naj vonja poteka tako
dolgo, dokler ne zmanjka goriva. Avto lahko vozi le v primeru, da je vgan (atribut avtoVzgan nastavljen
na true) in ima trenutno hitrost vejo kot 0.
NajvecjiCas(): metoda vrne podatek, koliko minut in sekund lahko e vozimo glede na trenutno
koliino goriva. Trenutno stanje avtomobila se ne spremeni.
Programiranje 1 VS Informatika
C# . NET
221
Doseg(l): metoda vrne podatek, koliko kilometrov lahko prevozimo z najvejo hitrostjo, e je v
rezervoarju e l litrov goriva. Trenutno stanje avtomobila se ne spremeni.
CasVoznje(d): metoda nam pove vrne koliko asa (v minutah in sekundah) potrebujemo, da prevozimo
d kilometrov, e vozimo z nespremenjeno hitrostjo, v rezervoarju pa imamo trenutno koliino goriva. Pri
tem je treba upotevati, da koliina goriva lahko tudi ne zadoa; v tem primeru bo treba ustaviti, ugasniti
avtomobil, napolniti rezervoar, ga znova prigati in odpeljati naprej, kar nam vzame dodatnih 15 minut.
Trenutno stanje avtomobila naj se sicer ne spremeni.
PotovalnaHitrost(d,t): metoda vrne hitrost, s katero naj avto vozi, da bi d km oddaljen kraj
dosegel v t minutah. Pri tem naj upoteva tudi eventuelna polnjenja rezervoarja, ki vzamejo dodatnih 15
minut. Trenutno stanje avtomobila se ne spremeni.
Pri vseh metodah predpostavljamo, da avto pri vseh hitrostih porabi enako koliino goriva.
Za generiranje avtomobilov sprogramirajte tri konstruktorje:
prvi naj bo brez parametrov in zgenerira avtomobil, ki ima vse atribute prazne (vrednost 0 ali false)
drugi naj ima le parameter s in naj zgenerira avtomobil s tevilko s, ostale vrednosti pa naj bodo prazne.
tretji naj ima parametre s, h, v in p, zgenerira pa naj avtomobil tevilke s, z najvejo hitrostjo h, velikostjo
rezervoarja v in povpreno porabo p. Atributi stevecKm, trenutnaHitrost in kolicinaGoriva naj imajo
vrednost 0, avtoVzgan pa na false.
Testiranje razreda
Za testiranje razreda Avto napiite razred TestAvto. Z uporabo vsakega konstruktorja definirajte po en avto. S
pomojo metod za nastavljanje atributov dopolnite podatke za prva dva avtomobila, nato pa izpiite vse
podatke o vseh avtomobilih. Z vsemi simulirajte polnjenje goriva, vonjo, spreminjanje hitrosti in vse
informativne izpise. Ponovno izpiite vse avtomobile ter jih primerjajte med seboj.
Programiranje 1 VS Informatika
C# . NET
222
C# . NET
223
- formatiranje diska
- poveanje kapacitete RAM-a
kar pretvorimo v spremenljivke in metode. Za spremenljivke izberemo smiselne tipe
spremenljivk, kar bi za primer z raunalnikom recimo lahko bilo:
stanje:
int HitrostProcesorja; // hitrost procesorja v megahercih
int KolicinaPomnilnika; // koliina RAM pomnilnika v megabajtih
int KapacitetaDiska; // kapaciteta diska v megabajtih
int HitrostCDEnote; // hitrost enote v faktorjih pisanja (52x, ...)
int SteviloUSBPrikljuckov; // tevilo USB prikljukov
bool Prizgan; // true, e je raunalnik pri gan, sicer false
bool PrikljucenTiskalnik; // true, e je prikljuen tisk., sicer false
C# . NET
224
Prav tako bi recimo lahko izboljali metodo za pri iganje (in tudi za ugaanje)
raunalnika. Ne glede na to, da vemo da bo po izvedeni metodi raunalnik ugasnjen,
bi
nas morda vseeno lahko zanimalo ali smo raunalnik zares ugasnili ali pa je e bil
ugasnjen. Torej, e smo ga zares ugasnili, bi vrnili za povratno infomracijo true, e pa
je
e bil ugasnjen, pa false. Tako bi sedaj metodo
void PrizgiRacunalnik(); // pri gi raunalnik
C# . NET
225
C# . NET
226
"Spreminjanje stanja" je lahko torej neposredno, kot v teh dveh metodah ali pa
posredno
v drugih metodah (kot je na primer pri pri iganju raunalnika). Posebni metodi sta pa
konstruktor in destruktor in imata imeni, enaki razredu. Medtem, ko je konstruktor
namenjen inicializaciji objekta, je destruktor namenjen pokonanju objekta in
"ienju"
dinamino dodeljenega prostora v asu delovanja objekta. Konstruktor se
avtomatsko
poklie, ko se rezervira prostor za objekt v pomnilniku, destruktor pa ko se unii.
Namen
konstruktorja je tako, da doloimo vrednosti razrednim spremenljivkam (ne nujno
vsem,
ampak kar pa potrebujemo). Loimo osnovni konstruktor (brez kakrnih parametrov)
in
dodatne konstruktorje. Medtem, ko je destruktor en sam, je lahko konstruktorjev
mnogo,
le razlikovati se morajo med seboj v parametrih, ki jih sprejmejo.
Primer osnovnega konstrukturja za raunalnik bi recimo bil naslednji:
CRacunalnik::CRacunalnik() {
HitrostProcesorja = 2000;
KolicinaPomnilnika = 512;
Prizgan = false;
TiskalnikPrikljucen = true;
}
C# . NET
227
je drugana metodi
medtem, ko metoda
predstavlja te avo, ker prevajalnik ne bo znal loiti med njima (med prvo in tretjo
metodo); obakrat namre gre za enak seznam parametrov (imena spremenljivk niso
pomembna, le tipi). Temu, da lahko uporabljamo ista imena za metode, v katerih se
pa
razlikuje seznam parametrov imenujemo preobloene metode (ang. overloading).
Po definiciji konstruktor ne vraa vrednosti. Na drugi strani se destruktor avtomatsko
poklie ob sproanju prostora v pomnilniku - ob unienju objekta. Ime je enako
razredu,
le da pred njim zapiemo znak ~ (tilda). Destruktor nima parametrov in prav tako ne
vraa nobene vrednosti.
Za na primer bo tako zelo preprost, da ne bo niti vseboval kode, v kolikor bi pa imeli
v
razrednih spremenljivkah na primer kakna dinamina polja in bi jih tekom uporabe
objekta kreirali z new, v destruktorju poskrbimo (e nismo e morda prej), da ta
dinamina polja odstranimo iz pomnilnika (stavke z delete prestavite torej v
destruktor).
CRacunalnik::~CRacunalnik() {
}
Vsi konstruktorji in destruktorji morajo biti nateti tudi v datoteki s konnico *.h (v
seznamu metod)!
Prizgan = false;
TiskalnikPrikljucen = true;
}
CRacunalnik::CRacunalnik(int HitProc, int KolPom) {
// parameter konstruktorja je hitrost procesorja in koliina pomnilnika
HitrostProcesorja = HitProc;
KolicinaPomnilnika = KolPom;
Programiranje 1 VS Informatika
C# . NET
228
Prizgan = false;
TiskalnikPrikljucen = true;
}
je drugana metodi
medtem, ko metoda
predstavlja te avo, ker prevajalnik ne bo znal loiti med njima (med prvo in tretjo
metodo); obakrat namre gre za enak seznam parametrov (imena spremenljivk niso
pomembna, le tipi). Temu, da lahko uporabljamo ista imena za metode, v katerih se
pa
razlikuje seznam parametrov imenujemo preobloene metode (ang. overloading).
Po definiciji konstruktor ne vraa vrednosti. Na drugi strani se destruktor avtomatsko
poklie ob sproanju prostora v pomnilniku - ob unienju objekta. Ime je enako
razredu,
le da pred njim zapiemo znak ~ (tilda). Destruktor nima parametrov in prav tako ne
vraa nobene vrednosti.
Za na primer bo tako zelo preprost, da ne bo niti vseboval kode, v kolikor bi pa imeli
v
razrednih spremenljivkah na primer kakna dinamina polja in bi jih tekom uporabe
objekta kreirali z new, v destruktorju poskrbimo (e nismo e morda prej), da ta
dinamina polja odstranimo iz pomnilnika (stavke z delete prestavite torej v
destruktor).
CRacunalnik::~CRacunalnik() {
}
Vsi konstruktorji in destruktorji morajo biti nateti tudi v datoteki s konnico *.h (v
seznamu metod)!
C# . NET
229
Uporabljamo jih lahko statino ali dinamino, pri emer v praksi prevladuje uporaba
dinaminega. Kot e reeno, razred definira nov tip spremenljivke in ga na tak nain
tudi
obravnavamo.
Za statino uporabo imamo torej naslednji "vzorec":
CRacunalnik MojRac1; // deklaracija objekta z imenom MojRac1
MojRac1.HitrostPomnilnika = ...; // direktni dostop do javne spremenljivke
MojRac1.KapacitetaDiska = ...; // to ne gre, ker je KapacitetaDiska
privatna!
MojRac1.PrizgiRacunalnik(); // klic javne metode
Programiranje 1 VS Informatika
C# . NET
230
Ker je z razredom definiran nov tip spremenljivke je treba v datoteki, kjer se uporablja
tak razred, podati kje se nahaja osnovna definicija razreda. Zato v glavi programa pri
direktivah include zapiemo za na primer:
#include "Racunalnik.h"
Programiranje 1 VS Informatika
C# . NET
231
Tocka.cpp:
#include "Tocka.h"
// osnovni konstruktor
CTocka::CTocka() {
X = 0;
Y = 0;
Z = 0;
}
// dodatni konstruktor
CTocka::CTocka(float X1, float Y1, float Z1) {
X = X1;
Y = Y1;
Z = Z1;
}
// destruktor
CTocka::~CTocka() {}
// izpis podatkov tocke
void CTocka::Izpis() {
printf("(%f,%f,%f)\n",X,Y,Z);
}
// pristevanje druge tocke (sprememba se pozna na razrednih spremenljivkah)
void CTocka::Sestej(float X1, float Y1, float Z1) {
X += X1;
Y += Y1;
Z += Z1;
}
// sestevanje z drugo tocko (sprememba je vrnjena v spremenljivkah X2,Y2,Z2
// razredne spremenljivke pa se ne spremenijo
void CTocka::Sestej(float X1,float Y1,float Z1,float &X2,float &Y2,float &Z2)
{
X2 = X+X1;
Y2 = Y+Y1;
Z2 = Z+Z1;
}
// pristevanje druge tocke, podane kot objekt (sprememba se pozna v razrednih
// spremenljivkah klicanega objekta; ne pa od T!)
void CTocka::Sestej(CTocka* T) {
X += T->X;
Y += T->Y;
Z += T->Z;
}
// sestevanje druge tocke (ni spremembe razrednih spremenljivk, se pa rezultat
// sestevanja vrne kot objekt!
CTocka* CTocka::Sestej(float X1, float Y1, float Z1) {
CTocka* Rezultat = new CTocka();
Rezultat->X = X+X1;
Rezultat->Y = Y+Y1;
Rezultat->Z = Z+Z1;
return(Rezultat);
}
C# . NET
232
V predzadnji metodi smo kot parameter metode uporabili objekt, oba tipa metod
(predzadnja in zadnja) pa sta v objektnem programiranju zelo pogosta.
e primer uporabe v glavnem programu:
#include "Tocka.h"
void main() {
CTocka* TockaA = new CTocka();
CTocka* TockaB = new CTocka(5,6,7);
CTocka* TockaC;
TockaA->Izpis();
TockaA->Y = 100;
TockaA->Izpis();
TockaB->Izpis();
TockaA->Sestej(1,2,3);
TockaA->Izpis();
TockaA->Sestej(TockaB);
TockaA->Izpis();
TockaC = TockaA->Sestej(10,20,30);
TockaC->Izpis();
TockaA->Izpis();
}
Programiranje 1 VS Informatika
C# . NET
233
Dvigalo.cpp:
#include "Dvigalo.h"
// osnovni konstruktor
CDvigalo::CDvigalo() {
Nadstropje = 0;
MaxNadstropje = 10;
SteviloOseb = 0;
TezaOseb = 0;
MaxTezaOseb = 800;
}
// dodatni konstruktor, ki posebej nastavi najvije nadstropje
CDvigalo::CDvigalo(int MaxNad) {
Nadstropje = 0;
MaxNadstropje = MaxNad;
SteviloOseb = 0;
TezaOseb = 0;
MaxTezaOseb = 800;
}
// dodatni konstruktor, ki posebej nastavi najvije nadstropje in najvejo
// dovoljeno te o
CDvigalo::CDvigalo(int MaxNad, int MaxTeza) {
Nadstropje = 0;
MaxNadstropje = MaxNad;
SteviloOseb = 0;
TezaOseb = 0;
MaxTezaOseb = MaxTeza;
}
// destruktor (v tem primeru je prazen)
CDvigalo::~CDvigalo() {}
// spuanje dvigala v ni ja nadstropja (e elimo spustiti ni je kot v
// klet ali pa e je eljeno nadstropje vije od trenutnega (torej ne gre za
// spuanje dvigala) javi false, sicer javi true in temu primerno a urira
// trenutno nadstropje dvigala
bool CDvigalo::SpustiDvigaloV(int Kam) {
if (Kam >= Nadstropje || Kam < 0)
return(false);
Nadstropje = Kam;
return(true);
}
// dviganje dvigala v ni ja nadstropja (e elimo spustiti vije kot na
// vrh ali pa e je eljeno nadstropje ni je od trenutnega (torej ne gre za
// dviganje dvigala) javi false, sicer javi true in temu primerno a urira
// trenutno nadstropje dvigala
bool CDvigalo::DvigniDvigaloV(int Kam) {
if (Kam <= Nadstropje || Kam > MaxNadstropje)
return(false);
Nadstropje = Kam;
return(true);
}
// vrne true, e je dvigalo v kleti, sicer vrne false
bool CDvigalo::JeDvigaloVKleti() {
Programiranje 1 VS Informatika
C# . NET
234
if (Nadstropje == 0)
return(true);
return(false);
}
// vrne true, e je dvigalu na vrhu (na najvijem mo nem nadstropju), sicer
// vrne false
bool CDvigalo::JeDvigaloNaVrhu() {
if (Nadstropje == MaxNadstropje)
return(true);
return(false);
}
// vrne true, e je v dvigalu kaj oseb (metoda bi bila ekvivalentna, e bi
// gledali ali je v dvigalu skupna te a oseb veja kot 0)
bool CDvigalo::JeVDvigaluKajOseb() {
if (SteviloOseb > 0)
return(true);
return(false);
}
// vstop ene osebe v dvigalo z doloeno te o (e te a presega najvejo
// dovoljeno skupno te o ali pa e je nepozitivna vrednost te e metoda javi
// false, sicer true)
bool VstopOsebe(int Teza) {
if (TezaOseb+Teza > MaxTeza || Teza < 0)
return(false);
SteviloOseb++;
TezaOseb += Teza;
return(true);
}
// izstop ene osebe iz dvigala z doloeno te o (e v dvigalu ni toliko te e
// ali pa e je nepozitivna vrednost te e metoda javi false, sicer true)
bool CDvigalo::IzstopOsebe(int Teza) {
if (TezaOseb > Teza || Teza < 0)
return(false);
SteviloOseb--;
TezaOseb -= Teza;
return(true);
}
// vstop ve oseb v dvigalo z doloeno te o (e te a presega najvejo
// dovoljeno skupno te o ali pa e je nepozitivna vrednost te e metoda javi
// false, sicer true)
bool VstopOseb(int StOseb, int Teza) {
if (TezaOseb+Teza > MaxTeza || Teza < 0)
return(false);
SteviloOseb += StOseb;
TezaOseb += Teza;
return(true);
}
// izstop ve oseb iz dvigala z doloeno te o (e v dvigalu ni toliko te e
// ali pa e je nepozitivna vrednost te e metoda javi false, sicer true)
bool CDvigalo::IzstopOseb(int StOseb, int Teza) {
if (TezaOseb > Teza || Teza < 0)
return(false);
SteviloOseb -= StOseb;
TezaOseb -= Teza;
return(true);
}
// izpis aktualnih podatkov od dvigala (trenutno nadstropje, tevilo oseb v
// dvigalu in njihova skupna te a)
void CDvigalo::IzpisStanjaDvigala() {
printf("trenutno v nadstropju : %d\n",Nadstropje);
printf("v njem stevilo oseb : %d s skupno tezo :
%d\n",SteviloOseb,TezaOseb);
}
2.5. Dedovanje
Programiranje 1 VS Informatika
C# . NET
235
Vsi nadrazredi (ker lahko razred naenkrat deduje lastnosti veih razredov) so nateti
za
dvopijem, pri emer moramo biti zelo pazljivi, da nadrazredi ne vsebujejo
istoimenskih
spremenljivk in metod, ker sicer pride do zmede. Pri dedovanju je e posebej
pomembno,
kaj je v nadrazredu doloeno kot privatno, kaj javno in kaj kot prijateljsko (ang.
friendly),
vendar to presega okvire vaj in tega teksta.
C# . NET
236
hitro")
4. Primeri iz izpitov
Napiite razreda CAlbum in CPesem. Razred CPesem naj vsebuje tipine podatke
neke
pesmi (naslov pesmi, avtor), ki naj bodo shranjene v privatnih spremenljivkah.
Vrednosti
teh spremenljivk naj bo mo no spremeniti in (loeno!) povpraati po njihovih
vrednostih
z javnimi metodami (torej 4 metode!). Razred CAlbum naj vsebuje v privatnih
spremenljivkah podatke o zalo bi albuma, tevilo pesmi in polje s podatki o pesmih
(polje objektov razreda CPesem). Velikost polja pesmi naj se doloi v konstruktorju
razreda CAlbum in takrat naj se v pomnilniku tudi rezervira prostor za polje pesmi.
Zapiite deklaracije in definicije metod obeh razredov, v delu programa (ne piite
vsega!)
pa naka ite, kako bi "pripravili" album dvajsetih razlinih avtorjev (vsak eno pesem) iz
koncertov na TUKu in kako bi ugotovili avtorja tretje pesmi na tem albumu.
class CPesem {
private:
char* Naslov;
char* Avtor;
public:
void NastaviNaslov(char* Nas);
void NastaviAvtorja(char* Avt);
char* DajNaslov();
char* DajAvtorja();
CPesem();
~CPesem();
};
CPesem::CPesem() {}
CPesem::~CPesem() {}
Programiranje 1 VS Informatika
C# . NET
237
4.2. CRacun
Napiite razred CRacun, ki predstavlja raun v nekem nakupu, npr. trgovini. Razred
naj
vsebuje metodo DodajNaRacun(char*, double, int), kjer boste "na raun" dodali novo
zadevo (z nekim imenom, ceno in tipom stopnje davka: 1 za recimo 10%, 2 recimo
za
20%). Prav tako naj obstaja metoda OdstraniIzRacuna(char*), kjer boste neko
zadevo
odstranili iz rauna. Dodatna naj bo e metoda IzpisRacuna(), kjer izpiete vse
zadeve, ki
so se nabrale "na raunu", njihovo skupno ceno in posebej, koliko zadev (tevilo in
njihova skupna cena) je bilo za stopnjo davka 1 in koliko za stopnjo davka 2. Sami
razmislite o tem, s katerimi spremenljivkami boste realizirali seznam zadev "na
raunu"
(naj jih bo recimo najve 30), za primerjavo nizov pa lahko uporabite kar vgrajeno
funkcijo strcmp! Napiite deklaracijo razreda (*.h), izvedbo metod (*.cpp) in kratek
primer uporabe, kjer boste uporabili te metode.
class CRacun {
private:
char** Stvari;
double* Cene;
int* Davki;
int SteviloStvari;
public:
void DodajNaRacun(char* Kaj, double Cena, int Davek);
void OdstraniIzRacuna(char* Kaj);
void IzpisRacuna();
Programiranje 1 VS Informatika
C# . NET
238
CRacun();
~CRacun();
};
CRacun::CRacun() {
Stvari = new char*[30];}
for (int i=0;i<30;i++)
Stvari[i] = new char*[100]; // recimo, da je ime izdelka najvec 100 znakov
SteviloStvari = 0;
}
CRacun::~CRacun() {
for (int i=0;i<30;i++)
delete[] Stvari[i];
delete Stvari;
}
void CRacun::DodajNaRacun(char* Kaj, double Cena, int Davek) {
if (SteviloStvari == 30) // je sploh se mozno dati kaj na racun?
return;
Stvari[SteviloStvari] = Kaj;
Cene[SteviloStvari] = Cena;
Davki[SteviloStvari] = Davek;
SteviloStvari++;
}
void CRacun::OdstraniIzRacuna(char* Kaj) {
for (int i=0;i<SteviloStvari;i++) {
if (strcmp(Stvari[i],Kaj) == 0) { // izdelek s tem imenom najden!
for (int j=i;j<SteviloStvari-1;j++) {
Stvari[j] = Stvari[j+1];
Cene[j] = Cene[j+1];
Davki[j] = Davki[j+1];
}
SteviloStvari--;
} // if
} // for i
}
void CRacun::IpisRacuna() {
double SkupnaCena = 0.0;
int KolikoDavek1 = 0;
int KolikoDavek2 = 0;
double SkupnaCenaDavek1 = 0.0;
double SkupnaCenaDavek2 = 0.0;
for (int i=0;i<SteviloStvari;i++) {
SkupnaCena += Cene[i];
if (Davki[i] == 1) {
KolikoDavek1++;
SkupnaCenaDavek1 += Cene[i];
}
else
KolikoDavek2++;
SkupnaCenaDavek2 += Cene[i];
}
}
printf("Stanje racuna:\n");
printf("stevilo izdelkov : %d\n",SteviloStvari);
printf("skupna cena izdelkov : %f\n",SkupnaCena);
printf("izdelkov dav. stopnje 1 : %d v skupni ceni : %f\n",KolikoDavek1,
SkupnaCenaDavek1);
printf("izdelkov dav. stopnje 2 : %d v skupni ceni : %f\n",KolikoDavek2,
SkupnaCenaDavek2);
}
4.3. CTekma
Napiite razred CTekma, ki predstavlja neko poljubno tekmo, recimo nogometno, ker
je
Programiranje 1 VS Informatika
C# . NET
239
to trenutno najbolj aktualno. Tekma se odvija med dvema motvoma (vsako motvo
ima
svoje ime), dogajanje na tekmi pa se bele i z naslednjimi metodami:
DalGol(ime_motva), RazveljaviGol(ime_motva), RumeniKarton(ime_motva),
RdeciKarton(ime_motva), Prekrek(ime_motva) in IzpisRezultata() ter
IzpisStatistike(ime motva). V teh metodah se motvu, katerega ime je podano kot
parameter: doda gol, razveljavi gol, zabele i dobljen rumeni in rdei karton, zabele i
napravljen prekrek, zadnji dve metodi pa sta namenjeni izpisu rezultata (koliko golov
je
na kateri strani) in statistiki tekme (rezultat, rumeni kartoni, rdei kartoni in prekrki).
Imena motev se doloita s parametroma v konstruktorju razreda. Sami razmislite o
tem,
s katerimi spremenljivkami boste realizirali statistiko (in rezultat tekme). Za primerjavo
nizov lahko uporabite kar vgrajeno funkcijo strmcp (<string.h>)! Napiite deklaracijo
razreda (*.h), izvedbo metod (*.cpp) in kratek primer uporabe, kjer boste uporabili te
metode.
class CTekma {
public:
char* ImeMostva1;
char* ImeMostva2;
int Gol1, Gol2;
int PrekrsekRu1, PrekrsekRu2;
int PrekrsekRd1, PrekrsekRd2;
int Prekrsek1, Prekrsek2;
void DalGol(char* Mostvo);
void RazveljaviGol(char* Mostvo);
void RumeniKarton(char* Mostvo);
void RdeciKarton(char* Mostvo);
void Prekrsek(char* Mostvo);
void IzpisRezultata();
CTekma(char* Mostvo1, char* Mostvo2);
~CTekma();
};
CTekma::CTekma(char* Mostvo1, char* Mostvo2) {
Gol1 = 0; Gol2 = 0;
PrekrsekRu1 = 0; PrekrsekRu2 = 0;
PrekrsekRd1 = 0; PrekrsekRd2 = 0;
Prekrsek1 = 0; Prekrsek2 = 0;
ImeMostva1 = Mostvo1; ImeMostva2 = Mostvo2;
}
CTekma::~CTekma() {}
void CTekma::DalGol(char* Mostvo) {
if (strcmp(Mostvo,ImeMostva1) == 0)
Gol1++;
else
Gol2++;
}
void CTekma::RazveljaviGol(char* Mostvo) {
if (strcmp(Mostvo,ImeMostva1) == 0)
Gol1--;
else
Gol2--;
}
void CTekma::RumeniKarton(char* Mostvo) {
if (strcmp(Mostvo,ImeMostva1) == 0)
PrekrsekRu1++;
else
PrekrsekRu2++;
}
void CTekma::RdeciKarton(char* Mostvo) {
Programiranje 1 VS Informatika
C# . NET
240
if (strcmp(Mostvo,ImeMostva1) == 0)
PrekrsekRd1++;
else
PrekrsekRd2++;
}
void CTekma::Prekrsek(char* Mostvo) {
if (strcmp(Mostvo,ImeMostva1) == 0)
Prekrsek1++;
else
Prekrsek2++;
}
void CTekma::IzpisRezultata() {
printf("Stanje na tekmi med %s in %s:\n",ImeMostva1,ImeMostva2);
printf("rezultat : %d:%d\n",Gol1,Gol2);
printf("prekrski : %d:%d\n",Prekrsek1,Prekrsek2);
printf("rumeni kartoni : %d:%d\n",PrekrsekRu1,PrekrsekRu2);
printf("rdeci kartoni : %d:%d\n",PrekrsekRd1,PrekrsekRd2);
}
Programiranje 1 VS Informatika