FK:P VT2004
Föreläsningsbilder F1
En inledning till Java och OOP
F1: 1
Några aspekter på ett nytt språk
• exekveringsmiljö (”nativ” kod eller interpretering m.m.)
• historik och designprinciper (varför språket ser ut som det gör)
• syntax för grundspråket (primitiva datatyper, satser osv)
• abstraktionsmekanismer (t.ex. egna datatyper, procedurer och funktioner
i Pascal, klasser och metoder mm i Java)
• standardbibliotek av färdiga programkomponenter
• standardverktyg för programutveckling (programmeringsmiljön:
kompilatorer, texteditorer, debuggers, dokumentationsverktyg,
programgeneratorer m.m.)
F1: 2
Java
• utformad 1991 av James Gossling vid Sun Microsystems under namnet Oak
• tänkt från början för programmering av elektroniska hemapparater i nätverk
• höga krav på
• flyttbarhet (skall kunna köras på olika processorer)
• driftsäkerhet (möjlighet att fånga upp och åtgärda felvid exekvering)
• säkerhet (möjlighet att begränsa programmets verksamhet)
• förberedelse för nedladdning över ett nät
• förberedelse för kommunikation över ett nät mellan samverkande program
• parallellt exekverande processer (”trådar”)
• omvandlad 1995 till Java och anpassad till programmering av tillämpningar för
WorldWideWeb, bl.a. omfattande stöd för grafik och animering
• utkommit sedan dess i flera versioner (1.0, 1.1, 1.2, 1.3, nuv. 1.4 och snart 1.5)
• objektorienterat språk
F1: 3
Java: kompilering och interpretering
Kompileras av
Källkod i Java
Prog.java
Javakompilatorn
javac
Programmet i
bytecode
Prog.class
Interpreteras
av
Java Virtual
Machine
En webbläsare
Exekveras på aktuell dator
F1: 4
Program i konventionella språk
Kompilator
för Windows
Länkare
för Windows
Exekverbart
program
för Windows
Objektkod
för Windows
Rutiner
för Windows
Källkod
i Pascal
Objektkod
för Macintosh
Exekverbart
program
för Macintosh
Rutiner
för Macintosh
Kompilator
för Macintosh
Länkare
för Macintosh
F1: 5
Program i Java
Javakompilator
Källkod
i Java
Java Virtual
Machine
för Windows
Java Virtual
Machine
för Macintosh
class-fil
i bytekod
class-fil
i bytekod
Andra klasser
F1: 6
Kortfattad språkhistoria
Fortran
1960
(IBM)
Blockstruktur (lokala variabler),
Algol procedurer, funktioner, parametrar,
datatyper, arrayer
Simula
1970
O-J. Dahl, K. Nygaard
Pascal (Norsk Regnesentral) OOP
C
N. Wirth
D. Ritchie
+ poster,
Systemprogrammering
pekare
Lågnivåmekanismer
mm
1980
J. Ichbiah (DOD) Ada
Modularitet,
Objekt-baserad prog,
Genericitet,
Parallellitet,
1990
Undantagshant.
2000
Smalltalk
A. Key (Xerox PARC)
C++
Ada95
... samt OOP
Generic Java
Java
J. Gossling(Sun)
OOP
Parallellitet
Undantagshant.
Java 1.5... samt genericitet
B. Stroustrup
Lågnivåmek.,
OBP, OOP,
Genericitet,
Undantagshant.
C# (MS)
F1: 7
Den C-aktiga syntaxen
Korthugget språk:
{ } istället för BEGIN END
inga ”onödiga” ord som PROCEDURE, FUNCTION, THEN osv
int[] arr; istället för
arr: ARRAY[1..10] OF Integer;
i = 0;
istället för
i := 0;
&& resp. ||
istället för
AND resp. OR
Vissa saker kan göras på flera olika sätt, t.ex. öka värdet i variabeln i med 1:
i = i + 1; eller
i += 1;
eller
++i;
Uttryck kan användas som satser, funktioner kan anropas som procedurer:
++i;
j = ++i;
summa(arr); // Returvärdet ignoreras, meningslöst här men tillåtet
F1: 8
Snabb syntaxjämförelse: Pascal ...
TYPE arrtyp = ARRAY [1..10] OF Integer;
PROCEDURE skriv(arr:arrtyp);
VAR i : Integer;
BEGIN
FOR i:=1 TO 10 DO
Write(arr[i]);
Writeln;
END; { las }
FUNCTION summa(arr:arrtyp):Integer;
VAR i, sum : Integer;
BEGIN
sum:=0;
FOR i:=1 TO 10 DO
sum := sum + arr[i];
summa:=sum;
END; { summa }
... kontra Java
void skriv(int[] arr){
for (int i = 0; i < 10; ++i)
System.out.print(arr[i]);
System.out.println();
} // summa
int summa(int[] arr){
int sum=0;
for (int i = 0; i < 10; ++i)
sum += arr[i];
return sum;
} // summa
F1: 9
Den största skillnaden: OOPHmm..slarviga
Java är ett objektorienterat språk.
definitioner
Objektorientering allmänt:
verkligheten består av objekt som kan ha tillstånd och beteende,
vissa objekt är av samma typ (klass),
objekten kan ha olika relationer med varandra,
klasser kan ha olika relationer med varandra (is-a, has-a)
Objektorienterad analys (OOA):
analysera (beskrivningen av) en verksamhet med avseende på vilka
typer av objekt som förekommer och vilka operationer som utförs på dem
Objektorienterad design (OOD):
utforma en systemarkitektur bestående av klasser med angivna relationer
mellan klasserna och operationer som skall kunna utföras på objekt av dessa
klasser
Objektorienterad programmering (OOP):
program byggs upp som en samling samarbetande objekt av klasser med
väldefinierade gränssnitt (operationer) och relationer. Varje klass utgör
en byggkloss som kan användas i flera program.
En objektorienterad systemarkitektur kan lätt översättas till ett program i ett
objektorienterat programmeringsspråk, men OOP handlar även om mer
konstruktionstekniska aspekter (t.ex. återanvändbara programkomponenter)
F1: 10
Topologin hos ett Pascalprogram
(eller program i något annat imperativt språk)
Centralt (globalt) lagrade data
som (kan) bearbetas av alla delar
av programmet.
Data
Subrutin
Subrutin
Subrutin
Vid ändringar av datastrukturen
kan alla delar av programmet
påverkas
Felaktigheter kan propageras
genom programmet och ge sig till
känna på ett helt annat ställe än
där de uppkommer - försvårad
felsökning och korrigering
Huvudprogram
F1: 11
Topologin hos ett modulärt program
Modul
Självständiga,
separatkompilerade moduler
som kommunicerar genom
väldefinierade gränssnitt
Modul
Modul
Modulgränssnitt uttryckta
i termer av abstrakta tjänster.
Modul
Data som behövs för att
implementera tjänsterna och
operationer på dessa data
inkapslade (encapsulated)
i modulen.
Data är gömda (oåtkomliga)
för andra moduler.
Huvudprogram
F1: 12
Exempel: användning av Javas bibliotek
import javax.swing.*;
import java.awt.*;
class Anteckning extends JFrame{
Anteckning(){
super("Anteckning");
JTextArea text = new JTextArea();
getContentPane().add(text, BorderLayout.CENTER);
setSize(300, 200);
show();
}
public static void main(String[] args){
new Anteckning();
}
}
Detta korta program skapar
ett fönster med där användaren
har fullständig inmatningsoch editeringsfunktionalitet.
F1: 13
API-beskrivningar
Användning av sådana komponenter ur biblioteket kräver mycket sökning
i beskrivningar av dessa komponenter efter vilka komponenter som finns,
vilka operationer de har och hur man använder dem.
På föreläsningar och lektioner hinner vi endast tipsa om de viktigaste
komponenterna och deras struktur, detaljer måste inhämtas på egen
hand från läroböcker men främst från de webbaserade API-beskrivningarna.
Detta gäller främst den senare delen av kursen.
Dessvärre kräver vissa enkla operationer också användning av komponenter.
T.ex. ett program som läser in en sträng från terminalfönstret och skriver ut den igen:
import java.io.*;
class Hej{
public static void main(String[] args) throws IOException{
BufferedReader input=new BufferedReader(
new InputStreamReader(System.in));
System.out.print(”Vad heter du? ”);
String namn = input.readLine();
System.out.println(”Hej, ” + namn);
}
}
F1: 14
Orientering om OOP: ett fånigt exempel
Säg att vi skall (börja) skriva det välkända Igelkottsprogrammet.
Programmet skall hantera igelkottar som har namn, ett antal taggar och som
kan bli platta (av att ha blivit överkörda). En platt igelkott har inga taggar.
Det man vill kunna göra med en igelkott är att få fram dess namn, dess antal taggar
och om den är platt. Man skall även kunna köra över en igelkott.
Man skall inte kunna ändra igelkottens namn.
Antalet taggar och plattheten kan man bara ändra genom att köra över igelkotten.
”Igge”
85
false
Igelkott
getNamn
bliPåkörd
getTaggar
ärPlatt
F1: 15
Klasser och objekt
Igelkott
namn
antalTaggar
platt
Klass
Typ
Skrivs i källkoden
Objekt
Instanser
Förekomster
Värden
Skapas
dynamiskt vid
exekvering
getNamn
bliPåkörd
getTaggar
ärPlatt
”Igge”
85
false
Igelkott
Igelkott
”Doris”
0
true
getNamn
bliPåkörd
getNamn
bliPåkörd
getTaggar
ärPlatt
getTaggar
ärPlatt
F1: 16
Koden för klassen Igelkott
public class Igelkott{
private String namn;
Data markerade som privata
private int antalTaggar;
private boolean platt;
public Igelkott(String n, int at){
”Konstruktor” som
namn = n;
anger hur objekt
antalTaggar = at;
platt = false;
skall initieras
}
public String getNamn() {
return namn;
}
public int getTaggar() {
return antalTaggar;
”Metoder” (dvs procedurer
}
eller funktioner) som
public boolean ärPlatt() {
anger operationer på
return platt;
ett igelkottobjekt
}
public void bliPåkörd() {
antalTaggar = 0;
platt = true;
}
public String toString(){
return namn + ” har ” + antalTaggar + ” taggar”;
}
F1: 17
}
Användning av klassen Igelkott
Klassen Igelkott läggs på filen Igelkott.java och kompileras för sig.
Detta resulterar i en fil Igelkott.class med den kompilerade bytekoden.
Nu kan man skriva en annan klass som kan använda klassen Igelkott:
public class AnnanKlass{
private Igelkott ig1, ig2;
public void någonMetod(){
ig1 = new Igelkott(”Igge”, 85);
ig2 = new Igelkott(”Doris”, 37);
String str = ig1.getNamn();
int antal = ig2.getTaggar();
ig2.bliPåkörd();
...
}
}
Klassnamnet Igelkott används som
typnamn för deklaration av ”pekarvariabler”
till Igelkott-objekt.
Igelkott-objekt skapas dynamiskt med new.
Vid skapande utförs objektens konstruktor,
man måste ange värden för dess parametrar.
F1: 18
Klasser och objekt igen
AnnanKlass
Igelkott
namn
antalTaggar
platt
ig2
ig1
någonMetod
getNamn
bliPåkörd
getTaggar
ärPlatt
AnnanKlass
ig2
ig1
någonMetod
”Igge”
85
false
Igelkott
Igelkott
”Doris”
0
true
getNamn
bliPåkörd
getNamn
bliPåkörd
getTaggar
ärPlatt
getTaggar
ärPlatt
F1: 19
Klasser kontra poster (RECORDs)
Det finns en stor likhet mellan klasser och poster.
Både klassobjekt och postförekomster innehåller värden på namngivna
attribut (termer, variabler).
Den stora skillnaden ligger i att klasser även innehåller operationer (metoder)
som kan anropas från utanför klassen för att t.ex. förändra värden hos det
objekt de anropas hos eller avläsa dessa värden.
Man brukar säga att ett objekt har ett tillstånd representerat av värden på dess
variabler (t.ex. namn, antalTaggar och platt) och ett beteende representerat av
dess metoder (t.ex. kan våra igelkottar tillfrågas om deras namn, antal taggar och
om de är platta, och de kan bli påkörda).
En annan viktig skillnad är att man kan gömma den inre implementeringen
av en klass genom att deklarera den som privat - andra klasser kan då
endast använda de publika metoderna för att ändra eller avläsa tillståndet.
På detta sätt kan man garantera att objekt av klassen beter sig korrekt.
T.ex. kan man inte ändra namn på våra igelkottar. Man kan inte heller ändra
deras antal taggar utan att köra på dem, och då blir de samtidigt platta.
Vi har alltså skapat en ny datatyp med bestämda operationer.
F1: 20
Mer om klasser och objekt
I Java finns det några primitiva datatyper som int, boolean, char,
double (motsv. Real) m.fl.
Allt annat är dock klasser, t.ex. String, Date och tusentals andra.
I ett Java-program måste varje sats ligga inom någon metod, och varje metod
måste ligga inom någon klass.
Av en anledning som vi återkommer till kan man endast skapa objekt dynamiskt
under exekveringen (liknande Pascals New) och de kan bara hanteras via ”pekare”.
Dock har dessa ”pekare” ett mer disciplinerat beteende än pekare i Pascal och
de kallas därför ”referenser” - man får inte kalla dem pekare.
Det finns ingen motsvarighet till Pascals Dispose. Istället tas objekten bort
automatiskt när det inte längre finns någon referens som refererar till dem
(automatisk skräpsamling - garbage collection).
F1: 21
Krav på generalitet
Eftersom de flesta klasser ska kunna användas av flera tillämpningsprogram måste
de utformas någorlunda generellt så att de inte bestämmer alltför mycket för
tillämpningarna.
Exempel på ett par enkla sådana krav på återanvändbara klasser är:
• man skriver inte ut felmeddelanden i klassen - man vet ju inte hur tillämpningen
vill hantera felet. Man försöker rapportera felet till tillämpningsprogrammet, inte
till användaren
• man skriver inte ut data, istället skapar man strängar som tillämpningar kan skriva
ut där de vill ha utskrifterna
•man läser inte in data, istället tar man emot strängar som man försöker tolka,
så tillämpningar kan läsa in strängen på det sätt de vill
F1: 22
Vem börjar skapa objekten?
AnnanKlass
ig2
ig1
någonMetod
Igelkott
namn
antalTaggar
platt
getNamn
bliPåkörd
getTaggar
ärPlatt
Om klasser bara är typbeskrivningar och det finns inget annat än klasser,
vem är det som skapar det första objektet?
Det måste finnas något som ”finns från början”, innan det finns några objekt.
Man kan deklarera metoder (och även variabler) som finns i en enda uppsättning
oberoende av objekten. De måste dock fortfarande finnas i någon klass.
De kallas för klassmetoder resp. -variabler.
I Java deklareras de med ordet static (”statiska” metoder resp. variabler)
F1: 23
Den ”statiska” metoden main
AnnanKlass
TestProg
ig2
ig1
någonMetod
main
Motsvarigheten till ett
huvudprogram måste
vara en statisk metod
med namnet main (och
vissa andra egenskaper).
Javas interpretator
anropar denna metod
när exekveringen startar,
i denna metod kan man
börja skapa objekt osv
Igelkott
namn
antalTaggar
platt
getNamn
bliPåkörd
getTaggar
ärPlatt
class TestProg{
public static void main(.....){
AnnanKlass ak = new AnnanKlass();
ak.någonMetod();
....
} // main
} // TestProg
F1: 24
Instans- kontra klass- variabler/metoder
Det vanliga är att varje objekt av en klass har sin egen uppsättning variabler och
metoder. De kallas då instans-variabler resp. -metoder.
Ibland händer det dock att man behöver någon variabel som alla objekt skall dela
på och som skall finnas även om det inte finns något objekt av klassen.
Det händer också att man behöver någon metod som hör till klassen men inte
behöver operera på objektens data och skall finnas oberoende av objekten
(se exempel på nästa bild).
Man kan då skapa en klassvariabel resp. klassmetod i klassen genom att deklarera
de ordet static.
F1: 25
Klassvariabler och -metoder
class Igelkott{
private static int antal=0;
private String namn;
...
public Igelkott(String n){
++antal;
namn = n;
....
}
public String getNamn(){
return namn;
}
}
public static int getAntal(){
return antal;
}
Anrop enligt:
String str = ig1.getNamn();
men:
int ant = Igelkott.getAntal();
Igelkott
namn
antal 1
getNamn
getTaggar
getAntal
ig1
Igelkott
”Igge”
getNamn
F1: 26
Objekt av samma men ändå olika typ
Säg att vi behöver ett program som hanterar djur av olika typer:
• alla djur kan äta och låta (ge läten)
• hästar kan springa
• kor kan ge mjölk
• fiskar kan simma och ”låter” annorlunda än alla andra djur
Fisk
Ko
Häst
äter
äter
äter
låter
låter
simmar
springer
gerMjölk
låter
F1: 27
Klasshierarkier, arv
Djur
äter
låter
Häst
Fisk
Ko
springer
simmar
gerMjölk
låter
Häst
äter
Djur
låter
springer
Fisk
Ko
äter
äter
Djur
låter
Häst
gerMjölk
Häst
Djur
låter
simmar
Fisk
låter
F1: 28
Klasshierarkier, arv
Klasser kan ordnas i en hierarkisk struktur, med den mest generella klassen
i toppen (klassen Djur i exemplet). Klasser på lägre nivåer (subklasser)
sägs ärva från klasser på högre nivåer (superklasser).
Subklasserna får alla de egenskaper som finns deklarerade i superklasserna
och kan lägga till sina egna egenskaper.
Dessutom kan subklasserna omdefiniera metoder från superklasserna klassen Fisk har definierat om metoden låter. Detta kallas ”överskuggning”
av superklassens metoder.
En referens deklarerad som Djur kan nu referera till objekt av antingen
klassen Häst, Ko eller Fisk. Om vi har referensen Djur d
och anropet
d.låter();
så går det inte att avgöra genom att titta på denna sats vilken metod låter
som kommer att anropas. Metoden bestäms vid anropsögonblicket beroende
på vilket objekt d råkar referera till då. Mekanismen kallas ”dynamisk
bindning”, möjligheten att med en sats kunna anropa olika metoder vid
olika tillfällen brukar kallas ”polymorfism”.
Det utgör den viktigaste mekanismen inom objektorienterad programmering.
F1: 29
Konsekvenser av OOP
Genom att varje klass är en självständig, separatkompilerad modul kan man
skapa bibliotek av återanvändbara programkomponenter och bygga
tillämpningsprogram av dessa byggklossar.
Genom användning av polymorfism kan man även anpassa beteendet hos dessa
byggklossar till varje tillämpnings önskemål.
I Javas klassbibliotek finns det återanvändbara klasser för olika typer av
datasamlingar (länkade listor, binära sökträd osv, sorterade och osorterade),
komponenter för grafiska användargränssnitt och hela färdiga applikationsramverk
som bara behöver fyllas i med innehållet i den aktuella tillämpningen.
F1: 30