Velkommen til INF1010 - våren 2012 I dag: Java datastrukturer Stein Gjessing Institutt for informatikk Universitetet i Oslo 1 1
I INF1010 skal du lære Å lage gode programmer Objektorientert programmering Ble funnet opp av Ole-Johan Dahl og Kristen Nygaard Det første objektorienterte språket het Simula I dag: Java datastrukturer Les: Litt om datastrukturer i Java av Stein Gjessing Det meste er repetisjon av INF1000 Litt mer om objekter i programmene våre et programmeringsmønster (så langt vi har tid) 2
Primitive typer, pekere og objekter Primitive typer: boolean, char, short, int, long, float, doubl Pekere til klasseobjekter til tabeller (arrayer) Objekter inneholder Variable og konstanter av de primitive typene eller pekere (data) Metoder En boks En variabel eller en konstant med en verdi av en primitiv type eller en peker inni (også kalt data) Et objekt Klasser er objektenes mønstre 3
Variable og konstanter (data) En variabel eller en konstant (av en primitiv type eller en peker) består av 3 ting: 1. Et navn 2. En (primitiv) type 3. Et innhold I programmet: int antall = 3; Når programmet utføres (inne i datamaskinen): En boks med navn og type utenpå, og en verdi inni type: int 3 navn: antall 4
Variable, tilordninger og uttrykk Vi gir variabler verdi ved en tilordningssetning, der likhetstegnet betyr settes lik: <venstreside> = <høyreside> 0. Hvis venstresiden deklarerer en variabel: Opprett denne 1. Regn ut høyresiden 2. Sett resultatet inn i variabelen på venstresiden type: int int antall = 3; antall = antall + 4; 37 navn: antall Variabelnavnet vil på venstre side av et likhetstegn bety lagerplassen som skal gis ny verdi. På høyre side av likhetstegnet betyr variabelnavnet den verdien som er lagret i boksen med dette navnet. 5
Java datastrukturer Hva skjer inne i en datamaskin når et Javaprogram blir utført? Masse elektroner farer rundt Umulig å skjønne Vi skal tegne det som foregår inne i datamaskinen når Javaprogrammet vårt blir utført Vi kaller det Java datastrukturtegninger Den som programmerer må ha fullstendig oversikt over det som foregår inne i maskinen (men ikke alt om gangen) Når jeg programmerer ser jeg for meg det som skal foregå inne i maskinen og skriver Java-instruksjoner for å få det til Noen ganger bare tenker jeg meg hvordan Java datastrukturen ser ut, andre ganger tegner jeg den (mer eller mindre fullstending) på papir 6
Program for salg av biler. public class BilSalg{ static BilSalg salgsobjekt; public static void main (String [ ] args) { salgsobjekt = new BilSalg ( ); BilSalg ( ) { int antallsteinb; Bil steinst = new Bil ( ); Bil oleso = new Bil ( ) ; steinst.foresporsel ( ); oleso.foresporsel ( ); steinst.foresporsel ( ); antallsteinb = steinst.finnantforesp(); System.out.println("Antall forespørsler på + Steins Toyota er " + antallsteinb); System.out.println("Antall forespørsler totalt + er nå " + Bil.finnTotal( ) ); //slutt konstruktør // slutt BilSalg class Bil { static private int total = 0; private int antforesporsler = 0; static int finntotal ( ) { return total; void foresporsel ( ) { antforesporsler ++; total ++; int finnantforesp ( ) { return antforesporsler; //slutt Bil 7
Vi skiller mellom Klasse-deklarasjonen i programteksten. Den er et mønster som brukes både når klassedatastrukturen lages (i det programmet starter opp) og senere når nye objekter lages. Klasse-datastrukturen, dvs. den (statiske) datastrukturen som lages i det programmet starter Objekt-datastrukturen (også bare kalt objekter eller klasse-objekter) som lages hver gang vi sier new. Utrolig Viktig! 8
BilSalg klassedatastruktur Navn: salgsobjekt null main Type: BilSalg salgsobjekt = new BilSalg ( ); Bil-objekt navn: antforesporsler 12 type: int 0 void foresporsel( ) Bil klassedatastruktur Navn: total 01 23 finntotal return total; Type: int BilSalg( ) navn: steinst Type: Bil navn: oleso Type: Bil navn: antallsteinb 2 int int antallsteinb; Bil steinst = new Bil ( ); Bil oleso = new Bil ( ) ; steinst.foresporsel ( ); oleso.foresporsel ( ); steinst.foresporsel ( ); antallsteinb = steinst.finnantforesp(); System.out.println("Antall forespørsler på + Steins Toyota er " + antallsteinb); System.out.println("Antall forespørsler totalt + er nå " + Bil.finnTotal( ) ); BilSalg-objekt antforesporsler ++; total ++; int finnantforesp( ) return (antforesporsler); Antall forespørsler på Steins Toyota er 2 Antall forespørsler totalt er nå 3 Bil-objekt navn: antforesporsler 1 type: int void foresporsel( ) 0 antforesporsler ++; total ++; int finnantforesp( ) return (antforesporsler); 9
Mer tegning (bare for å demonstrere variable og objekter) Java datastrukturtegninger m/parametre Filen heter BrukSum.java class Sum { int tall = 11; static int statt = 12; public void skrivt (int tl) { int sum; sum = tall + statt + BrukSum.tall1 + tl; System.out.println("Summen er " + sum); // slutt Sum Oversettes og kjøres med >javac BrukSum.java >java BrukSum Oversetteren lager to filer: BrukSum.class og Sum.class Java fikling public class BrukSum { static int tall1 = 16; static int tall2 = 10; int ubrukt = 15; public static void main(string [ ] args) { Sum testpeker; tall1 = 13; testpeker = new Sum( ); testpeker.skrivt(tall2+4); // slutt BrukSum 10
Java datastruktur-tegning ved kjøring av BrukSum klassedatastruktur BrukSum main navn: args navn: tall1 13 16 type: int navn: tall2 10 type: int type: String[] navn: testpeker type: Sum tall1 = 13; testpeker = new Sum( ); testpeker.skrivt(tall2+4); navn: statt 12 type: int Objekt av klassen Sum skrivt(int tl) navn: tall 11 type: int navn: sum 50 type: int navn: tl 14 type: int Klassedatastruktur Sum int sum; sum = tall + statt + BrukSum.tall1 + tl; System.out.println( Summen er + sum); Summen er 50 11
Li' om $lgang $l egenskaper i objekter private betyr at den ikke er kjent utenom klassen public betyr at den sees av alle Ingen modifikator betyr at egenskapen er kjent innenfor filen/katalogen/pakken 12
Eksempel på Java datastrukturtegning + Programmeringsmønsteret Modell - Utsyn - Kontroll (MVC - Model, View, Control) 13
Et bankprogram Vi skal lage et program som håndterer kontoene i en bank. En konto eies av en kunde, og har en saldo. Programmet skal kommunisere med en bruker i Unix/DOS- vinduet Programmet skal kunne administrere kontoene i banken, og i første omgang 1) Oppre'e en ny konto 2) Fjerne en konto 3) Se'e inn penger på en konto 4) Skrive ut bankens forvaltningskapital 14
Et bankprogram n Vi skal lage et program som håndterer kontoene i en bank. En konto eies av en kunde, og har en saldo. Vi bruker substantivmetoden til å finne forslag til klasser (som vi kan lage objekter fra) class Bank class Konto class Kunde class Saldo For kunde og saldo satser vi i denne enkle versjonen av programmet på å bare bruke h.h.v. en String og en double 15
class Bank I en bank skal vi kunne legge inn en ny kunde, _erne en kunde, se'e inn penger på en kundes konto og finne forvaltningskapitalen $l banken (summen av alle beløpene på alle kontoene) class BankData Alle kontoene blir adminstrert av klassen BankData class Konto Data og metoder for en konto 16
UML klassediagram (mer i INF1050): Bank BankData 1 1 1 Konto Sammenlign med Java datastrukturen på neste side (UML er ikke viktig i INF1010) 17
Skisse av Java datastruktur for banksystemet Bank-objekt BankData-objekt Mange Konto-objekter 18
UML klassediagram for BankData BankData Konto 1 Kan f.eks. gi denne Java datastrukturen: Konto-objekter BankData-objekt navn: type: Bank type: HashMap type: Bank HashMap-objekt En Collection 19
Skisse av class BankData Bank-objekt navn: konti type: HashMap BankData( ) lagbankkunde (...) fjernbankkunde (...) settinn (...) sumallekonti ( ) class BankData { BankData( ) {... private HashMap <String,Konto> konti = new HashMap<String,Konto>( ); public void lagbankkunde(string navn) {... public void fjernbankkunde (String n) {... public void settinn(string n, double b) {... double sumallekonti( ) {... 20
class Konto Når en konto oppre'es oppgir vi dens eier, og saldoen se'es $l null. På en konto skal vi kunne se'e inn et beløp, finne navnet på eieren og finne innestående beløp 21
Skisse av class Konto Konto-objekt Konto(String nvn) class Konto { Konto (String nvn) {... public void setinn(double belop) {... settinn(double belop) double hentsaldo( ) String henteier( ) public double hentsaldo ( ) {... public String henteier( ) {... // slutt klassen Konto 22
Kjente mønstre for programoppdeling Det er mange kjente og velprøvde måter å dele opp programkode. Slike kjente måter kalles design pa'erns. Ta' fra The Timeless Way of Building, Christoffer Alexander, Oxford University Press, 1979, ISBN 0195024028 Each pa'ern describes a problem which occurs over and over again in our environment, and then describes the core of the solu$on to that problem, in such away that you can use this solu$on a million $mes over, without doing it the same way twice Et slikt programmeringsmønster har dere lært i INF1000 med kommandoløkka som skriver ut en meny og tar kommando fra brukeren. Et av de mest kjente: Modell - Utsyn - Kontroll skal dere lære her (Trygve Reenskaug) 23
Modell Utsyn Kontroll = MVC: Model View Control Modell En ren datastruktur som holder alle data om problemet. Utsyn Egen modul for å presentere modellen for brukeren på ulike måter valgt av brukeren (via kontrollen) Kontroll Egen modul/klasse for å mo'a ordre fra brukeren og enten endre modellen (legge inn nye data, endre, _erne data) eller kalle en funksjon i utsynet for å gi et ny' bilde av modellen. Omlag samme oppdeling som i klient/tjener baserte distribuerte systemer Modell database (server) Utsyn klienten på distribuerte PCer Kontroll tjener/server med forretningslogikken Tjener (med forretningslogikk) Klienter Database server 24
Modell - Utsyn - Kontroll (MVC) Her: Et svært enkelt system for å vise mekanismen. MVC er fortrukket ved noen hundre linjer kode og oppover. Grunnen $l å skille disse funksjonene fra hverandre, er at det gjør det le'ere : Å utvikle - Konsentrere seg om en $ng om gangen Å endre - Kode om en $ng er samlet e' sted F.eks.: Linjebasert vs. Vindusbasert utskrio 25
MVC løsning for banken vår Det skal da være klasser som håndterer : Klassen BankData med hjelpeklassen Konto Utsynet for hele systemet (BankUtsyn) Kontrollen for hele systemet (Bank) 26
Java datastruktur oversikt Bank-objekt BankData-objekt konti BankUtsyn-objekt Konto-objekter <Alt som har med presentasjon og interaksjon med brukere> 27
Programskisse av hele Banksystemet Kontroll av Banksystemet public class Bank { private BankData b; private BankUtsyn u; public Bank( ) { b = new BankData( ); u = new BankUtsyn( ); public static void main (String [] args) { Bank bnk; bnk = new Bank( ); bnk.ordreløkke( ); void ordreløkke ( ) { // end Bank Prøv å kompilere (oversette) og kjøre denne skissen Utsyn for Bank class BankUtsyn { <Alt som har med presentasjon og interaksjon med brukere> BankData class BankData { <administrerer alle kontoene> Konto class Konto <data om en konto>
Bankklassedatastruktur main navn: bnk type: Bank bnk = new Bank(); bnk.ordreløkke(); navn: b Bank-objekt Bank type: BankData BankData-objekt lagnykunde lagbankkunde fjernbankkunde fjernbankkunde settinn sumallekonti sumallekonti settinn ordrelokke navn: konti BankUtsyn-objekt leskommando beomnavnogbelop hentnavn hentbelop beomoghentnavn skrivsum navn: u type: BankUtsyn HashMap-objekt type: HashMap Konto-objekter 29
Fullstendig program import java.util.; En konto har en eier identifisert av en tekst (String) @author Stein Gjessing @version 13. januar 2011 class Konto { private String navn; private double saldo; Konstruktør setter kontoens saldo til 0. @param n navn på kontoens eier Konto (String n) { navn = n; saldo =0; Setter inn et beløp. @param b beløp public void setinn(double b) { saldo += b; Henter saldoen. @return saldo på konto public double hentsaldo() { return saldo; Henter eier. @return navn på eier public String henteier() { return navn; 30
BankData er modellen / dataene i banksystemet. Denne klassen innehold er alle metoder som er nødvendige for å manipulere kontoer. En ny bank innholder ingen kontoer. Alle kontoenes eiere må ha forskjellige navn @author Stein Gjessing @versjon 13. januar 2011 class BankData { private HashMap <String,Konto> konti = new HashMap<String,Konto>(); Oppretter en ny konto i banken. @param kunde navn på kunden public void lagbankkunde(string navn) { konti.put(navn, new Konto (navn)); Fjerne en konto fra banken. @param navn navn på kunde public void fjernbankkunde(string navn) { konti.remove(navn); Summerer saldoen for alle kontoene i banken. @return summen av saldo for alle kontoer public double sumallekonti() { double sum = 0; for (Konto s: konti.values()) sum+= s.hentsaldo(); return sum; Setter inn penger på en konto. @param navn navn på kunde @param belop beløpet som settes inn. public void settinn (String navn, double belop) { Konto k = konti.get(navn); k.setinn(belop); 31
Bank er kontrollklassen for dette banksystemet. Her ligger ordreløkken som styrer det hele. Denne klassen er bindeleddet mellom utsynet og datamodellen. @author Stein Gjessing @version 17. Januar 2011 public class Bank { private BankData b; private BankUtsyn u; Bank() { b = new BankData(); u = new BankUtsyn(); public static void main(string [] args) { Bank bnk = new Bank(); bnk.ordreløkke(); Lager en ny konto. void lagnykunde () { String nvn = u.beomoghentnavn(); b.lagbankkunde(nvn); Fjerner en konto. void fjernbankkunde () { String nvn = u.beomoghentnavn(); b.fjernbankkunde(nvn); Setter inn penger på en konto. Nødvendig informasjon hentes via ustynet. void settinn() { u.beomnavnogbelop(); String navn = u.hentnavn(); double bel = u.hentbelop(); b.settinn(navn,bel); Henter summen av saldo fra alle kontoer og viser resultatet ved hjelp av utsyn void sumallekonti() { double sum = 0; sum = b.sumallekonti(); u.skrivsum(sum); Ordreløkken som styrer kommandoene. void ordreløkke () { int valg; valg = u.leskommando(); while(valg!= 0) { switch (valg) { case 1: lagnykunde(); break; case 2: fjernbankkunde(); break; case 3: settinn(); break; case 4: sumallekonti(); break; default: u.skrivfeil("gi tall mellom 0-4"); valg = u.leskommando(); // end ordreløkke // end class Bank 32
BankUtsyn brukes til innlesing og vising av kundedata. @author Stein Gjessing @version 13. Januar 2011 class BankUtsyn { private Scanner tast; // tast gir kortvarig oppbevaring av leste data private String navn; private double belop; Konstruktør BankUtsyn( ) { tast = new Scanner(System.in); Skriver ut menyen og leser inn kommandovalget. @return kommandovalget public int leskommando() { System.out.println("\nMeny: "); System.out.println("0 - avslutt"); System.out.println("1 - Opprett ny kunde "); System.out.println("2 - Fjern kunde"); System.out.println("3 - Sett inn penger"); System.out.println("4 - Finn forvaltningskapital"); System.out.print(" Velg funksjon: "); return (tast.nextint()); Ber om navn og beløp og lagrer. public void beomnavnogbelop() { System.out.print("\nGi navn og beløp (på hver sin linje): "); navn = tast.next(); belop = tast.nextdouble(); Henter navnet som er lest inn. @return navnet public String hentnavn() { return navn; Henter bløpet som er lest inn. @return beløpet public double hentbelop() { return belop; Ber om og henter et navn. @return navnet public String beomoghentnavn() { System.out.print("\nGi navn : "); return tast.next(); 33
Skriver ut bankens forvaltningskapital. @param sum kapitalen som skrives ut public void skrivsum(double sum) { System.out.println("\nBankens forvaltningskapital: + sum); Skriver ut en feilmelding. @param feil feilmeldingen public void skrivfeil(string feil) { System.out.println(feil); // end BankUtsyn Kjør: >javadoc -package Bank.java 34
Tes$ng (mer i INF1050) Alle klasser og metoder testes først separat, så samlet Regresstes$ng kjør alle gamle tester + evt. nye hver gang noe endres (ikke bare test det nye med nye tester) Tes$ng kan aldri vise fravær av feil, bare at systemet virker for visse inndata. Bevis av programmer? Særs vanskelig og dyrt Lønner seg bare i helt spesielle $lfeller 35
Dokumentasjon, brukeropplæring, innføring Ikke del av de'e kurset, men meget vik$g. Dekkes av andre kurs, bl.a. INF1050 VIKTIG! 36