27.07.2013 Views

overlæsning, klassefelter og -metoder (static), konstante felter

overlæsning, klassefelter og -metoder (static), konstante felter

overlæsning, klassefelter og -metoder (static), konstante felter

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Pr<strong>og</strong>rammering 2004<br />

Forelæsning 3, tirsdag 14. september 2004<br />

• Indkapsling <strong>og</strong> synlighed<br />

• Overlæsning<br />

• Klasse<strong>felter</strong> <strong>og</strong> -<strong>metoder</strong><br />

• Konstante <strong>felter</strong><br />

• Betingede ordrer: if-else, if<br />

• Indlejrede betingede ordrer<br />

• Blokke<br />

• L<strong>og</strong>iske udtryk<br />

• Semikoloner. . .<br />

• Indrykning<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-1<br />

Klassen Time fra sidste forelæsning<br />

public class Time {<br />

private int hours, min; // since midnight<br />

public Time(int hours, int min) {<br />

this.hours = hours; this.min = min;<br />

}<br />

public String twoDigits(int n) { // used in toString<br />

return "" + (n / 10) + (n % 10);<br />

}<br />

public String toString() {<br />

return twoDigits(hours) + "." + twoDigits(min);<br />

}<br />

public Time plus(int m) { // return new Time m minutes later<br />

int totalmin = 60 * hours + min + m;<br />

return new Time(totalmin / 60, totalmin % 60);<br />

}<br />

public int to(Time t) { // return number of minutes to t<br />

return 60 * t.hours + t.min - 60 * hours - min;<br />

}<br />

public void move(int m) { // move time by m minutes<br />

int totalmin = 60 * hours + min + m;<br />

hours = totalmin / 60; min = totalmin % 60;<br />

}<br />

}<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-2<br />

Indkapsling <strong>og</strong> synlighed: private <strong>felter</strong> <strong>og</strong> <strong>metoder</strong><br />

Felter der erklæres private kan kun ses <strong>og</strong> ændres inde i klassen:<br />

class Time {<br />

private int hours, min;<br />

...<br />

}<br />

De kan ikke læses eller ændres af <strong>metoder</strong> der hører til andre klasser.<br />

God (objektorienteret) pr<strong>og</strong>rammeringsskik:<br />

• Lav alle <strong>felter</strong> private<br />

• Hvis et felt skal kunne aflæses udefra, så definér en public get-metode for feltet:<br />

public int getHours() {<br />

return hours;<br />

}<br />

Så skal brugere af Time-klassen skrive t1.getHours() i stedet for t1.hours<br />

Metoder kan <strong>og</strong>så erklæres private i stedet for public, hvis de kun skal kunne bruges i klassen selv.<br />

Opgave: Bør twoDigits være private?<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-3<br />

Hvorfor gøre livet besværligt for andre klasser?<br />

• For at sikre dataintegritet i Time-klassen:<br />

Det er f.eks. ønskeligt at konstruktorer <strong>og</strong> <strong>metoder</strong> i Time sikrer at 0 ≤ min ≤ 59.<br />

Men så kan vi jo ikke tillade udefrakommende at udføre eksempelvis t1.min = 62.<br />

Altså må andre klasser ikke få adgang til feltet min.<br />

• For at sikre at man kan skifte datarepræsentation i Time-klassen:<br />

Vi kunne ombestemme os <strong>og</strong> repræsentere et tidspunkt som antal minutter siden midnat:<br />

class Time {<br />

int min; // Since midnight<br />

...<br />

}<br />

Det ville faktisk gøre de fleste <strong>metoder</strong> i Time simplere.<br />

Men hvis der stod t1.hours alle mulige andre steder i pr<strong>og</strong>rammet, skulle det rettes alle de steder.<br />

Hvis der står t1.getHours() i stedet, så skal vi kun rette ét sted, i Time-klassen:<br />

public int getHours() {<br />

return min / 60;<br />

}<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-4


Overlæsning af konstruktorer <strong>og</strong> <strong>metoder</strong><br />

En konstruktor er karakteriseret ved sin signatur.<br />

Signaturen er konstruktorens navn (som er klassens navn) samt typerne af dens formelle parametre.<br />

Eksempel: Signaturen for konstruktoren Time fra før er ‘Time(int, int)’.<br />

En klasse kan have flere konstruktorer (som jo har samme navn) så længe deres signaturer er forskellige.<br />

Dette kaldes <strong>overlæsning</strong> af konstruktoren. På engelsk: ‘overloading’.<br />

Metoder kan overlæsses lige som konstruktorer.<br />

D.v.s. at der kan være flere <strong>metoder</strong> med samme navn men forskellige signaturer i en klasse.<br />

En metodes signatur er dens navn samt typerne af dens formelle parametre.<br />

Metodens resultat-type indgår ikke i signaturen.<br />

Overlæssede <strong>metoder</strong> med samme navn kan have forskellige resultat-typer.<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-5<br />

Eksempel: Overlæsning af konstruktorer i Time<br />

public class Time {<br />

private int hours, min; // since midnight<br />

}<br />

public Time(int hours, int min) {<br />

this.hours = hours;<br />

this.min = min;<br />

}<br />

public Time(int hours) {<br />

this.hours = hours;<br />

this.min = 0;<br />

}<br />

public Time(Time t) {<br />

this.hours = t.hours;<br />

this.min = t.min;<br />

}<br />

... <strong>metoder</strong> uændrede ...<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-6<br />

Test af ny Time klasse<br />

public class TestTime2 {<br />

}<br />

public <strong>static</strong> void main(String[] args) {<br />

Time t0, t1, t2, t3;<br />

t0 = new Time(12);<br />

t1 = new Time(12, 35); // A<br />

System.out.println("t0 = " + t0);<br />

System.out.println("t1 = " + t1);<br />

}<br />

t2 = t1.plus(40);<br />

t3 = new Time(t1);<br />

t1.move(45); // B<br />

System.out.println("t1 = " + t1);<br />

System.out.println("t2 = " + t2);<br />

System.out.println("t3 = " + t3);<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-7<br />

Datamatens hukommelse ved kørsel af TestTime2<br />

A<br />

t0 t1 t2 t3<br />

: Time<br />

hours 12<br />

min 0<br />

twoDigits<br />

toString<br />

plus<br />

to<br />

move<br />

B t0 t1 t2 t3<br />

: Time<br />

hours 12<br />

min 0<br />

twoDigits<br />

toString<br />

plus<br />

to<br />

move<br />

hours<br />

min<br />

: Time<br />

hours 12<br />

min 35<br />

twoDigits<br />

toString<br />

plus<br />

to<br />

move<br />

: Time<br />

twoDigits<br />

toString<br />

plus<br />

to<br />

move<br />

: Time<br />

12 13 hours 13<br />

35 20 min 15<br />

twoDigits<br />

toString<br />

plus<br />

to<br />

move<br />

: Time<br />

hours 12<br />

min 35<br />

twoDigits<br />

toString<br />

plus<br />

to<br />

move<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-8


Overlæsning af konstruktorer, this()<br />

Det er muligt fra en konstruktor at kalde en anden af klassens konstruktorer.<br />

Den anden konstruktor kaldes med det specielle metodekald<br />

this( argumenter )<br />

Alternativ udgave af konstruktorerne i Time:<br />

public class Time {<br />

private int hours, min; // since midnight<br />

}<br />

public Time(int hours, int min) {<br />

this.hours = hours;<br />

this.min = min;<br />

}<br />

public Time(int hours) {<br />

this(hours,0);<br />

}<br />

public Time(Time t) {<br />

this(t.hours,t.min);<br />

}<br />

... <strong>metoder</strong> uændrede ...<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-9<br />

Klasse<strong>felter</strong> <strong>og</strong> -<strong>metoder</strong>: <strong>static</strong><br />

Felter kan erklæres som fælles for klassen frem for tilhørende hvert objekt.<br />

Fælles <strong>klasse<strong>felter</strong></strong> erklæres med nøgleordet <strong>static</strong>.<br />

<strong>static</strong> standard<br />

Antal kopier Én fælles Én for hvert objekt<br />

Fælles for klasse Ja Nej<br />

Tilsvarende kan en metode erklæres <strong>static</strong> hvis den ikke afhænger af et objekts <strong>felter</strong>.<br />

Eksempel 1: main metoden i pr<strong>og</strong>rammer er <strong>static</strong>, den kaldes uden at der skabes et objekt af dens klasse.<br />

Eksempel 2: Metoden twoDigits i Time klassen kunne være <strong>static</strong>.<br />

Konstante <strong>felter</strong>: final<br />

Med nøgleordet final kan man erklære at et felt ikke må ændres.<br />

final standard<br />

Kan ændres Nej Ja<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-10<br />

Eksempel: Person med entydigt løbenummer (TaltPerson)<br />

public class TaltPerson {<br />

private String fornavne;<br />

private String efternavn;<br />

public final int nummer; // Løbenummer<br />

}<br />

// Tæl hvor mange personer, der er oprettet<br />

private <strong>static</strong> int antalPersoner = 0;<br />

public <strong>static</strong> int getAntalPersoner() {<br />

return antalPersoner;<br />

}<br />

public TaltPerson(String f, String e) {<br />

fornavne = f;<br />

efternavn = e;<br />

antalPersoner = antalPersoner + 1;<br />

nummer = antalPersoner;<br />

}<br />

// ... Øvrige <strong>metoder</strong> som i Person klassen<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-11<br />

Test af TaltPerson<br />

public class TestTaltPerson {<br />

public <strong>static</strong> void main(String [] args) {<br />

TaltPerson georg = new TaltPerson("Georg","Brandes");<br />

TaltPerson tove = new TaltPerson("Tove","Ditlevsen");<br />

TaltPerson dan = new TaltPerson("Dan","Turell");<br />

}<br />

}<br />

System.out.println("Der er oprettet " + TaltPerson.getAntalPersoner() +<br />

" personer");<br />

System.out.println(tove + " er nummer " + tove.nummer);<br />

// tove.nummer = 5; // ulovligt, nummer er final<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-12


Datamatens hukommelse ved kørsel af TestTaltPerson<br />

Class TaltPerson<br />

antalPersoner 0 1<br />

2 3<br />

getAntalPersoner<br />

: TaltPerson<br />

fornavne<br />

efternavn<br />

nummer 1<br />

setFornavne<br />

setEfternavn<br />

getFornavne<br />

getEfternavn<br />

toString<br />

: TaltPerson<br />

fornavne<br />

efternavn<br />

nummer 3<br />

setFornavne<br />

setEfternavn<br />

getFornavne<br />

getEfternavn<br />

toString<br />

: String<br />

"Georg"<br />

: String<br />

"Brandes"<br />

: String<br />

"Dan"<br />

: String<br />

"Turell"<br />

georg<br />

dan<br />

: TaltPerson<br />

fornavne<br />

efternavn<br />

nummer 2<br />

setFornavne<br />

setEfternavn<br />

getFornavne<br />

getEfternavn<br />

toString<br />

: String<br />

"Tove"<br />

: String<br />

tove<br />

"Ditlevsen"<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-13<br />

Betingede ordrer: if-else<br />

Pr<strong>og</strong>rammer skal kunne vælge mellem forskellige alternativer.<br />

Generelt format for if-else ordre:<br />

if (udtryk)<br />

ordre1<br />

else<br />

ordre2<br />

Betingelsen udtryk skal have en værdi af typen boolean, dvs.true eller false.<br />

Virkning:<br />

1. Beregn værdien af udtryk,<br />

2. hvis true så udfør ordre1, ellers udfør ordre2.<br />

Dvs. at if-else vælger mellem to ordrer, afhængigt af udtryk.<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-14<br />

Eksempel med if-else:<br />

En klasse til at repræsentere karakterer efter 13-skalaen:<br />

public class Karakter {<br />

public final int tal; // karakterens talværdi, 0 til 13<br />

}<br />

public Karakter(int tal) {<br />

this.tal=tal;<br />

}<br />

public String toString() {<br />

if (tal < 5)<br />

return "0" + tal;<br />

else<br />

return "" + tal;<br />

}<br />

public boolean erBestaaet() {<br />

return tal >= 6;<br />

}<br />

public String resultat() {<br />

if ( erBestaaet() )<br />

return "bestået";<br />

else<br />

return "dumpet";<br />

}<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-15<br />

Brug af Karakter klassen:<br />

public class TestKarakter1 {<br />

}<br />

<strong>static</strong> void udskrivResultat(Karakter k) {<br />

System.out.println("Med " + k + " er man " + k.resultat());<br />

}<br />

public <strong>static</strong> void main(String [] args) {<br />

udskrivResultat( new Karakter(5) );<br />

udskrivResultat( new Karakter(6) );<br />

udskrivResultat( new Karakter(10) );<br />

udskrivResultat( new Karakter(3) );<br />

}<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-16


Betingede ordrer, if<br />

public class TestKarakter2 {<br />

}<br />

<strong>static</strong> void udskrivResultat(Karakter k) {<br />

if ( k.erBestaaet() )<br />

System.out.print("Hurra! ");<br />

System.out.println("Med " + k + " er man " + k.resultat());<br />

}<br />

public <strong>static</strong> void main(String [] args) {<br />

// ... samme som før<br />

}<br />

Generelt format:<br />

if (udtryk)<br />

ordre1<br />

Virkning:<br />

1. Beregn værdien af udtryk,<br />

2. hvis true udfør ordre1.<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-17<br />

En almindelig fejl<br />

Opgave: Hvad ville der ske hvis udskrivResultat i stedet var skrevet som neden for?<br />

<strong>static</strong> void udskrivResultat(Karakter k) {<br />

if ( k.erBestaaet() );<br />

System.out.print("Hurra! ");<br />

System.out.println("Med " + k + " er man " + k.resultat());<br />

}<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-18<br />

En blok består af flere ordrer<br />

En række ordrer kan grupperes til én ordre med { ... }:<br />

En blok kan forekomme hvor som helst en ordre kan forekomme.<br />

public class TestKarakter3 {<br />

<strong>static</strong> int antalBestaaet = 0;<br />

}<br />

<strong>static</strong> void udskrivResultat(Karakter k) {<br />

if ( k.erBestaaet() ) {<br />

System.out.print("Hurra! ");<br />

antalBestaaet = antalBestaaet + 1;<br />

}<br />

System.out.println("Med " + k + " er man " + k.resultat());<br />

}<br />

public <strong>static</strong> void main(String [] args) {<br />

udskrivResultat( new Karakter(5) );<br />

udskrivResultat( new Karakter(6) );<br />

udskrivResultat( new Karakter(10) );<br />

udskrivResultat( new Karakter(3) );<br />

System.out.println("Antal bestået: " + antalBestaaet);<br />

}<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-19<br />

En anden almindelig fejl<br />

Opgave: Hvad ville der ske hvis udskrivResultat i stedet var skrevet som neden for?<br />

<strong>static</strong> void udskrivResultat(Karakter k) {<br />

if ( k.erBestaaet() )<br />

System.out.print("Hurra! ");<br />

antalBestaaet = antalBestaaet + 1;<br />

System.out.println("Med " + k + " er man " + k.resultat());<br />

}<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-20


else-problemet<br />

Hvad giver dette hvis x er 4:<br />

if (x > 5)<br />

if (y > 5)<br />

System.out.println("gren A");<br />

else<br />

System.out.println("gren B");<br />

Regel: En else-gren knytter sig til den seneste uafsluttede if.<br />

Man kan afslutte en if ved at lukke den inde i en blok:<br />

if (x > 5) {<br />

if (y > 5)<br />

System.out.println("gren A");<br />

} else<br />

System.out.println("gren B");<br />

Brug gerne ekstra { ... } til at gøre meningen med en ordre klar.<br />

Ligesom man bruger ekstra ( ... ) til at gøre meningen med et regneudtryk klar.<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-21<br />

Sammenligningsoperatorer<br />

Operator Betydning Eksempel<br />

== Lig med x == 60<br />

!= Forskellig fra x != 60<br />

< Mindre end x < 60<br />

60<br />

>= Større end eller lig med x >= 60<br />

Bemærk: Sammenligningsoperatorerne virker kun for tal, ikke for tegnstrenge <strong>og</strong> andre objekter.<br />

Resultattypen er boolean, dvs.true eller false.<br />

Sammenligningsoperatorerne har alle samme præcedens <strong>og</strong> lavere præcedens (binder svagere) end de<br />

aritmetiske operatorer (regnearterne).<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-22<br />

L<strong>og</strong>iske operatorer<br />

L<strong>og</strong>iske operatorer i præcedensorden fra høj til lav præcedens:<br />

Operator Betydning Eksempel<br />

! Ikke (Negation) !(x == 60)<br />

&& Og (Konjunktion) 0 = 60<br />

Argumenttyperne er boolean <strong>og</strong> resultattypen er boolean.<br />

! har højere præcedens (binder stærkere) end sammenlignings- <strong>og</strong> aritmetiske operatorer mens && <strong>og</strong> || har<br />

lavere præcedens (binder svagere) end sammenligningsoperatorerne.<br />

Udtrykket udregnes fra venstre mod højre.<br />

Hvis udtryk1 er falsk i udtryk1 && udtryk2 så udregnes udtryk2 ikke.<br />

Hvis udtryk1 er sandt i udtryk1 || udtryk2 så udregnes udtryk2 ikke.<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-23<br />

Små opgaver i l<strong>og</strong>iske udtryk<br />

Heltallet m er mindst 1 <strong>og</strong> højst 12.<br />

Tallet h er større end eller lig med nul, <strong>og</strong> mindre end 24.<br />

x i anden er mindre end 25.<br />

y er mindre end 40 eller større end 100<br />

aar er delelig med 4.<br />

aar er ikke delelig med 100.<br />

aar er delelig med 400.<br />

aar er et skudår: delelig med 4 men ikke med 100, eller delelig med 400.<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-24


Hvor skal der semikolon?<br />

• Intet semikolon efter if (men muligvis efter grenene).<br />

• Put semikolon efter en ordre lavet af et udtryk: tildeling, metodekald, osv.<br />

• Put semikolon efter en return ordre.<br />

• Put semikolon efter variabel-erklæringer.<br />

• Der skal ikke semikolon efter en blok { ... }.<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-25<br />

Hvor skal der semikolon(er):<br />

if (x != 0) {<br />

sum = sum + 1.0/x<br />

antal = antal + 1<br />

}<br />

Hvor skal der semikolon(er):<br />

if (x != 0)<br />

sum = sum + 1.0/x<br />

else<br />

sum = 0<br />

Hvor skal der semikolon(er):<br />

if (x != 0)<br />

sum = sum + 1.0/x<br />

else<br />

{ sum = 0 }<br />

Hvor skal der semikolon(er):<br />

if (x != 0)<br />

sum = sum + 1.0/x<br />

else<br />

if (y != 0)<br />

sum = sum + 1.0/y<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-26<br />

Pr<strong>og</strong>ramlayout, indrykning<br />

Indrykning har ikke n<strong>og</strong>en betydning for datamaskinen.<br />

Men for mennesker er det meget nemmere at læse<br />

<strong>static</strong> void udskrivResultat(Karakter k) {<br />

if ( k.erBestaaet() ) {<br />

System.out.print("Hurra! ");<br />

antalBestaaet = antalBestaaet + 1;<br />

}<br />

System.out.println("Med " + k + " er man " + k.resultat());<br />

}<br />

end at læse<br />

<strong>static</strong> void udskrivResultat(Karakter k) { if ( k.erBestaaet() ) {<br />

System.out.print("Hurra! "); antalBestaaet = antalBestaaet + 1;<br />

} System.out.println("Med " + k + " er man " + k.resultat()); }<br />

Datamaskinen er ligeglad, men det er jeres lærer ikke. . .<br />

Indryk altid underordnede linier (grenene i en if, ordrer i en blok, indmaden i <strong>metoder</strong>, ...)<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-27<br />

Nyt idag<br />

• Synlighed: private <strong>og</strong> public<br />

• Overlæsning<br />

• Klasse<strong>felter</strong> <strong>og</strong> -<strong>metoder</strong> (<strong>static</strong>)<br />

• Konstante <strong>felter</strong> (final)<br />

• Betingede sætninger: if-else, if<br />

• Blokke<br />

• L<strong>og</strong>iske udtryk<br />

Læsning for idag: Morelli,<br />

kapitel 3 t.o.m. s. 147, undt. 3.6.5,<br />

kapitel 5 t.o.m. s. 259 midt, undt. 5.6.6.<br />

Pr<strong>og</strong>rammering 2004 KVL Side 3-28

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!