overlæsning, klassefelter og -metoder (static), konstante felter
overlæsning, klassefelter og -metoder (static), konstante felter
overlæsning, klassefelter og -metoder (static), konstante felter
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