Kurt Nørmark ©
Department of Computer Science, Aalborg University, Denmark
September 2001
Abstract Previous lecture Next lecture Index References Contents | Denne lektion fortsætter hvor den forrige slap. Vi studerer information hiding i Java, pakkebegrebet, værktøj i JDK programmeringsomgivelsen, klassevariable og metoder. Vi slutter af med at se på programbeskrivelse kontra programudførelse. |
Pakker, import og class path |
Pakke-begrebet i Java Slide Note Contents Index References Speak | Hvis man har mange klasser er det en praktisk nødvendighed at kunne gruppere disse på en hierarkisk måde. Det er netop det man kan med Java's pakkebegreb. |
The concept pakke: En pakke i Java er en mængde af logisk sammenhørende klasser | Pakkebegrebet tillader os at gruppere klasserne i logisk sammenhørende delmængder |
|
|
|
Anbefalet organisering af klasser Slide Note Contents Index References Speak | Vi beskriver her en anbefalet og relativ simpel strukturering af klasser i filer og pakker. Virkeligheden er dog mere kompliceret end dette. Vi vender tilbage til dette på den efterfølgende side |
Pakker og klasser navngives med et punktum imellem niveauerne. Eksempelvis refererer 'P.Q.C' til klassen C i pakken Q, som er indeholdt i pakken P. I filsystemet indeholder kataloget P kataloget Q, som igen indeholder filen C.java. På et Unix system adresserer vi klassen som P/Q/C.java (på en PC som P\Q\C.java) |
Alternative organiseringer af klasser Slide Note Contents Index References Speak | Det er undertiden praktisk at have mere end én klasse pr. fil. Dette er specielt tilfældet hvis man har mange små 'hjælpe klasser'. Det kan også være praktisk at overveje en katalogvis separering af Java kilde filer fra Java byte kode filer. |
|
|
Tilgang til klasser i andre pakker Slide Note Contents Index References Speak | Klasser i samme pakke kan umiddelbart tilgå hinanden. Det betyder f.eks. at en klasse umiddelbart kan lave instanser af en anden klasse i samme pakke. De to klasser kan umiddelbart 'bruge hinanden'. Anderledes forholder det sig for klasser i forskellige pakker |
|
At java.lang altid er importeret betyder, at klasserne i denne pakke altid er umiddelbart til rådighed for java programmøren |
|
Eksempel på klasser i pakker Slide Note Contents Index References Speak | Her viser vi tre klasser i to pakker som en konkret illustration af indholdet på de forrige sider |
|
Program: En klasse Class A som benytter ClassB og ClassC fra pakken enPakke.
Bemærk ClassB importeres, men at ClassC ikke importeres. Dette vil være ganske underligt i et
virkeligt og praktisk program. Her har vi gjort denne forskel for at illustrere forskellen mellem
en importeret klasse (ClassB) og en ikke importeret klassse (ClassC). |
|
Program: En klasse ClassB i pakken enPakke. ClassB skal være public i sin pakke for at kunne
anvendes fra en anden pakke. |
|
Program: En klasse ClassC ganske tilsvarende til ClassB. |
|
Hvordan lokaliseres en klasse? Slide Note Contents Index References Speak | Klasser benytter sig typisk af andre klasser. Problemstillingen, som vi her ser på, er hvordan compileren og fortolkeren lokaliserer de klasser, der er behov for. Vi ser specielt på en angivelse af den såkaldte class path. Vi vil her interessere os for de mere princielle forhold omkring lokalisering af klasser. For detaljer henvises til JDK dokumentationen, hvortil vi refererer nedenfor. |
Behovet opstår f.eks. når vi i et program skal type checke et kald af en metode, som befinder sig i en klasse i en anden fil. Java værktøjet vil i dette tilfælde forsøge at finde den oversatte fil eller kilde filen, hvor klassen befinder sig. |
The concept Class path: Class path definerer steder i filsystemet (pakker) hvor Java værktøjet leder efter klasser, som ikke er systemklasser og udvidelsesklasser | Systemklasserne definerer selve java platformen; disse leveres med JDK omgivelsen. Udvidelsesklasserne (extensions) er pakker af udvidelser til Java platformen, som typisk befinder sig i et bestemt og fast katalog. Hvis alle java filer befinder sig i 'det nuværende katalog' er det ikke nødvendigt at bekymre sig om class path. Hver sti i class path peger på et katalog eller zip/jar fil, som repræsenterer en Java pakke. |
Figure. Vi ser en skitse af et filsystem hvor classpath udpeger en mængde af 'punkter'. Disse punkter er de ydre pakker, som kan indeholde filer med klasser. Punkterne kan også indeholde andre pakker med filer og eller pakker. De markerede, lysegrønne områder er således de områder, der kan indeholde java class filer. | ![]() |
|
|
Information hiding |
Information hiding i forskellige objekt-orienterede sprog Slide Note Contents Index References Speak | Som allerede omtalt i den første lektion er kontrol af synlighed af variable og metoder et meget væsentligt element af objekt-orienteret programmering. Vi starter med at se på nogle generelle forhold om information hiding i objekt-orienterede programmeringssprog |
|
|
|
|
Information hiding i Java Slide Note Contents Index References Speak | Vi vil nu se på hvordan Java understøtter information hiding. For fuldstændighedens skyld nævner vi også nogle synlighedsforhold, som først for alvor gør sig gældende når vi begynder at beskæftige os med nedarvning. I diskussionen på de følgende sider omtaler vi pakker (packages). En pakke er en samling af klasser, som hører logisk sammen (og som befinder sig i samme katalog i filsystemet). Vi ser på pakker senere i denne lektion. |
Java benytter såkaldte modifiers til angivelse af synlighed. Modifiers benyttes også til angivelse af andre egenskaber, såsom 'final' (konstant) og 'static' Det virker sært at Java ikke understøtter en 'modifier' for package synlighed. Protectede egenskaber er underligt urene i Java, idet denne form for synlighed både involverer pakke-synlighed og subklasse-synlighed. Specielt er det tricket at forstå hvorledes subklasser i fremmede pakker håndteres. Mere om dette i lektionen om nedarvning. |
|
Information hiding i Konto Slide Note Contents Index References Speak |
Program: Vi ser her anvendelsen af synligheds modifiers i klassen Konto. Som det ses har vi
fulgt anbefalingen om at instansvariablene er private. Bemærk, at konsekvensen af
dette er, at vi skal definere trivielle metoder til aflæsning af de relevante
instansvariable. balance er en sådan metode |
|
|
Mere om information hiding Slide Note Contents Index References Speak |
|
Opgave: Klassen Rectangle Slide Note Contents Index References Speak | Her introducerer vi én af denne lektions opgaver |
Exercise 4.1. Programmering af klassen Rectangle | Denne opgave går ud på at programmere en klasse Rectangle. (En sådan klasse findes i forvejen i
Java klassebiblioteket, men dette ignorerer vi i denne opgave). Et rektangel er et velkendt geometrisk
objekt med en bestemt placering i et todimensionelt koordinatsystem. I denne opgave
vil vi afgrænse os til at arbejde med rektangler, hvis sider er parallelle med akserne i koordinatsystemet.
Antag også at vi arbejder med heltallige koordinater og dimensioner. Start med at beslutte hvordan I vil repræsentere et rektangel. Datarepræsentationen skal være skjult for klienter af rektanglet. Implementer følgende konstruktorer og metoder i Rectangle:
Det vanskeligste aspekt af klassen Rectangle er metoden overlappingRectangle. Det kan være en god hjælp at bruge klassen Interval (udviklet til formålet) hvori der findes en metode, der returnerer overlappet mellem to intervaller. Dokumenter endvidere klassens konstruktorer og metoder, og producer HTML dokumentation ved brug af værktøjet javadoc. |
Værktøj |
Værktøj i Javaprogrammerings omgivelsen Slide Note Contents Index References Speak | Værktøj i en programmeringsomgivelse er programmer, som arbejder på andre programmer. Et typisk værtøj er en compiler eller en editor |
The concept programmeringsomgivelse: En programmeringsomgivelse er en mere eller mindre integreret mængde af programudviklingsværktøj, som understøtter programudviklingsprocessen | Ordet programmeringsomgivelse bruges om samlingen af værktøj, som understøtter 'det at udvikle programmer'. I nogle systemer er samlingen af værktøj integreret tæt i hinanden (måske så tæt, at man slet ikke fornemmer eksistensen af individuelt værktøj). Dette var situation i Turbo Pascal, som de fleste kender. I andre systemer er værktøjerne meget isolerede og separate; Programmøren er her bevidst om, at omgivelsen består af flere stykker værktøj | |
The concept Java Development Kit: Java Development Kit (JDK) indeholder et antal basale værktøjer, som gør det muligt at oversætte og udføre Java programmer | Java development Kit (JDK) er en samling af værktøj, som kun er løst integreret. De vigtigste og mest centrale værktøjer er compileren og fortolkeren; men der findes en del andre værktøjer, som understøtter Java programmøren |
|
|
Værktøj i Javaprogrammerings omgivelsen Slide Note Contents Index References Speak | Værktøj i en programmeringsomgivelse er programmer, som arbejder på andre programmer. Et typisk værtøj er en compiler eller en editor |
|
|
|
Et eksempel på brug af javadoc Slide Note Contents Index References Speak | Vi ser her hvordan grænsefladen af klassen Konto, som vi har studeret adskillige gange indtil nu, kan dokumenteres ved brug af JavaDoc værktøjet. |
Program: Man kan køre javadoc på dette program med javadoc -d docs Konto.java. Dette skaber
grænseflade dokumentation af Konto i underkataloget docs. |
|
|
Klasseegenskaber |
Klassevariable og klassemetoder Slide Note Contents Index References Speak | Vi vil her studere et alternativ til instansvariable og (instans)metoder, som vi hidtil har set på, nemlig de såkaldte klassevariable og klassemetoder. På næste side ser vi på, hvorledes disse begreber understøttes i Java |
The concept klassevariabel: En klassevariabel er en variabel, som er fælles for alle instanserne af en klasse | Vi har defineret en klassevariabel som en variabel, der er fælles for alle instanser af en klasse. Vi kunne, alternativt, definere en klassevariabel som en instansvariabel i klassen af metaobjektet (altså i metaklassen), jf. nedenstående snak om metaobjekter. | |
The concept klassemetode: En klassemetode er en metode, der opererer på klassen som et objekt. |
Java skaber en instans c af klassen Class når en bestemt klasse loades. Objektet c repræsenterer således klassen's egenskaber på køretidspunktet. Man kan spørge: Hvordan får jeg fat i det objekt, som repræsenterer en bestemt klasse. Svaret er: obj.getClass(). Metoden getClass er en af de få metoder i klassen Object (roden i klassehierarkiet). Hvis man kender navnet på klassen (fuldt navn incl. pakke) kan man finde det objekt, som repræsenterer klassen via den statiske metode forName(String) i klassen Class. |
|
Statiske egenskaber af en klasse i Java Slide Note Contents Index References Speak | Statiske egenskaber, erklæret ved brug af nøgleordet static, kendes også fra C. Men det er vigtigt at forstå, at der er stor forskel på betydningen af static i C og Java. I Java er betydningen i grove træk at en egenskab er klassetilknyttet i modsætning til at være objekt-tilknyttet. I C er der flere forskellig betydninger. En statisk variabel eller funktion har et scope der er begrænset til den fil, hvori den er erklæret. Statiske lokale variable i en C funktion nedlægges ikke mellem kald af funktionen. |
|
Eksempel. Metoden isDigit i klassen Character er et eksempel på en klassemetode i Java |
Konstanter erklærers ofte for statiske i Java idet en mængde af objekter lige så godt kan deles om sådanne. Konstanter erklæres således for det meste som 'final static' i Java |
|
Initialisering af klassevariable i Java Slide Note Contents Index References Speak | Kontruktorerne har til opgave at initialisere instansvariablene i Java. Men hvordan initialiseres klassevariablene i Java. Det er problemstillingen vi ser på her. |
I langt de fleste situation kan statiske variabel initialiseres med en 'initializer' umiddelbart
i forlængelse af definitionen: |
Syntax: Syntaksen af en static block, hvori statiske variable (klasse variable) kan initialiseres. Semantisk set udføres blokkens kommandoer kun én gang, nemlig når klassen 'loades'. |
|
Program: Et eksempel på en statisk initialiseringsblok.
En klasse som viser et eksempel på brugen af en statisk initialiseringsblok.
I blokken initialiseres to arrays som tabellægger sinus og cosinus i et interval.
Vi forestiller os, at en sådan tabel kan være nyttig i Circle klassen, og ikke mindst hurtigere
end beregning af sinus og cosinus via funktionskald. Eksemplet er taget fra bogen 'Java in A Nutshell',
2, edition, af David Flanagan, fra O'Reilly. |
|
Instans initialiseringsblokke er en sædvanlig blok af kommandoer, som kan placeres en vilkårlig sted i en klasse. I forbindelse med skabelse af objekter bliver sådanne blokke udført (i en ganske bestemt rækkefølge, på et ganske bestemt tidspunkt i forhold til konstruktoren: før klassens konstruktor, men efter udførelse af superklassen's konstruktor). Man kan placere vilkårligt program i sådanne blokke. Men lad vær'! Det vil ikke give gode programmer, og der er stor fare for, at en sådan programmeringsstil vil fjerne sig fra den objekt-orienterede stil vi går efter på dette kursus. |
|
Udførelse |
Programbeskrivelse kontra programudførelse Slide Note Contents Index References Speak | Det er meget vigtigt at holde programbeskrivelsen (klasserne) adskilt fra programudførelsen (objekter, med indbyrdes referencer). I nogle sprog er klasser også objekter, som kan manipuleres af et sæt af operationer. Disse kaldes for metaobjekter. Smalltalk og CLOS er eksempler på sådanne sprog. Når klasser også er objekter, kan man spørge sig selv, hvilke klasser klasse-objekterne er instanser af? Normalt kalder man klasser, hvis instanser repræsenterer klasser, for metaklasser. Operationerne i disse metaklasser tillader, at man undersøger og påvirker aspekter af programmet selv. Med en passende organisering af programmeringsomgivelsen befordrer metaobjekterne at et program kan tilgå information om sig selv. Dette kaldes undertiden for refleksion. Dette er imidlertid et videregående emne, som ikke berøres yderligere på dette kursus |
The concept programbeskrivelse: Statisk programbeskrivelse som det fremgår af programteksten
| At programbeskrivelsen omtales som statisk betyder, at det er relativ uforanderlig. Dette skal naturligvis ses i forhold til programudførelsen. Programbeskrivelsen er dog foranderlig i den forstand at programmøren via værktøj i programmeringsomgivelsen kan ændre den | |
The concept programudførelse: Dynamisk programudførelse som det forekommer i maskinen, når programmet kører
| Programudførelsen's elementer ændrer sig hele tiden, som en funktion af tiden. |
Det nuværende objekt kan i et Java program refereres via nøgleordet this |
Objekt-interaktion Slide Note Contents Index References Speak | Objekter interagerer som bekendt med hinanden ved at sende beskeder. Vi vil her se på et scenario som illustrerer, hvordan objekt-interaktion kan udvikle sig mellem 'et netværk' af objekter. Vi fokuserer både på objekterne under udførelsen, og på de bagved liggende klasser i programbeskrivelsen |
|
Image series: Et scenarie hvor et kundeobjekt indsætter 500 kroner i banken. | Et scenarie hvor et kundeobjekt indsætter 500 kroner i banken. Vi viser objekt-interaktionen som følger af, at en kunde sætter 500 kroner i banken. Det nuværende objekt er vist med rød farve. Vi skitserer endvidere programmet i de klasser i bankprogrammet som er involveret i interaktionen. |
Image no. 1. En kunde sender beskeden indsæt til sin bank. Via parametre angives, at der skal indsættes 500 kroner på konto 'K1234' | ![]() |
Image no. 2. Bank objektet finder kontoen frem ved at sende en besked til et objekt, som repræsenterer samlingen af bankkonti i banken | ![]() |
Image no. 3. Objektet, som repræsenterer samlingen af bankkonti finder kontoen i en database, og metoden findKonto returnerer kontoen til banken | ![]() |
Image no. 4. Banken sender beskeden indsæt til den fremfundne konto. Som parameter angives beløbet | ![]() |
Image no. 5. I kontoen aktiveres metoden indsæt, som opdaterer kontoen's saldo | ![]() |
Image no. 6. Banken er igen det nuværende objekt. Banken sender beskeden gemKonto til samlingen af bankkonti. Kontoen sendes med som parameter. | ![]() |
Image no. 7. Vi ser metoden gemKonto i klassen KontoSamling, som blev aktiveret af banken. Hermed slutter scenariet. | ![]() |
Det er ofte vanskeligt at afgøre i hvilket objekt man skal placere en given funktionalitet |
Eksempel. Skal beskeden gemKonto sendes til enKontoSamling med enKonto som parameter eller Skal beskeden gemKonto sendes til enKonto med enKontoSamling som parameter | Vi stødte på denne problemstilling i scenariet ovenfor. Her valgte vi at lade kontosamlingen være ansvarlig for fremskaffelse og lagring af konti. Alternativt kunne vi flytte ansvaret for lagring af en konto til Kontoklasse. I dette tilfælde er det naturligt at 'find' og 'gem' er metoder i samme klasse |
Vi henviser til hosstående reference for en yderligere diskussion af ansvarsfordeling |
|
Hvordan starter udførelsen af et objekt-orienteret program? Slide Note Contents Index References Speak |
|
|
'Multidotning' i Java Slide Note Contents Index References Speak |
Symbolerne x, y, z osv. kan være instansvariable eller beskeder (metode aktiveringer). I sidstnævnte tilfælde skal der i Java også være parenteser med evt. aktuelle parametre |
Når vi siger at et udtryk 'syntaktisk hænger sammen' på en bestemt måde kunne vi også tale om parsning af udtrykket. Parsning betyder at uddrage struktur af en flad præsentation, i dette tilfælde en tekststreng, som repræsenterer udtrykket |
Mere 'multidotning' i Java Slide Note Contents Index References Speak |
|
Program: Et Java program som illustrerer multidotning i kombination med metode aktivering.
Beskeden anotherC(5) sendes til obj (et C objekt), som returnerer et nyt C objekt, der
sendes beskeden anotherC(6), der returnerer et nyt C objekt, der sendes beskeden anotherC(7),
der returnerer et nyt C objekt, hvis reference assignes til res. Programmet udskriver tallet 28 |
|
Program: Et tilsvarende Java program som undgår brug af multidotning.
Mellemresultaterne lagres i variablene res1 og res2 |
|
Indlejring af klasser i hinanden |
Oversigt over indlejring af klasser Slide Note Contents Index References Speak | Vi starter med en oversigt over mulighederne for at indlejre klasser i hinanden. På de følgende sider vil vi se nærmere på nogle detaljer omkring dette. Hvis man ønsker at studere dette emne nærmere kan jeg anbefale et kapitel af bogen 'Java in a nutshell', jf. referencen nederst fra denne side. |
Observationen om, at det er muligt at definere en klasse i kroppen af en metode er interessant set på baggrund af, at metoder ikke kan indlejres i hinanden på samme måde som vi f.eks. i Pascal kan have procedurer lokalt i procedurer. |
Hvad vi her kalder indre statiske klasser omtales i The Java Tutorial som 'nested classes'. |
|
Indre statiske klasser Slide Note Contents Index References Speak |
Observationen nummer to afspejler helt normal principper for blokstruktur: En lokal definition kan se og anvende alle egenskaber fra mere globale definitioner. Sådan er det også når vi indlejrer procedurer i hinanden. |
Ligesom det er muligt statisk at indlejere klasser i hinanden, kan vi også indlejre interfaces statisk i en klasse. Interfaces hører vi mere om i en senere lektion |
Eksempel. Klassen Spillekort kan indlejres statisk i klassen KortSpil. Dermed understreger vi samhørigheden mellem kort begrebet og et helt spil kort samtidig med at vi accepterer at enkeltkort kan eksistere uafhængigt af helhedsobjektet. |
Program: En skitse af den statiske indlejring af klassen Spillekort i KortSpil.
|
|
Exercise 4.2. Klasserne Spillekort og KortSpil | I forrige lektion var der en opgave om Spillekort, hvor klassen Spillekort repræsenterer
et enkelt kort i et kortspil. Da nogen måske ikke nåede at programmere Spillekort klassen sidste gang, er det en mulighed at løse opgaven ved øvelserne idag. I min løsning har jeg implementeret en klasse KortSpil, som repræsenterer de 52 kort i spil kort (uden jokere). Vi har ovenfor anbefalet at indlejere Spillekort statisk i KortSpil. Afprøv denne løsning konkret, og demonstrer ved et eksempel, at der statig er adgang til SpilleKort (uden at gå igennem et KortSpil objekt) selv om den er indlejret i KortSpil. |
Husk i denne sammenhæng på at C1 objekter ikke bliver del-objekter af C1 objekter. |
|
Indre klasser Slide Note Contents Index References Speak | Vi ser her på indre, ikke-statiske klasser. Overfladisk er forskellen blot, at den indre klasse ikke angiver 'static' foran klassedefinitionen. Men som vi vil se er forskellen på semantikken meget stor og væsentlig |
|
Figure. En klasse Outer med en indre klasse Inner. Programmet vises herunder. | ![]() |
Program: Klassen Outer med den indre klasse Inner.
Når vi laver en instans af Outer vil konstruktoren
instantiere Inner. Ligeledes vil 'fabrikations metoden' makeInner lave en instans af Inner, som
returneres til en klient af Outer. Dette vil betyde at en klient af Outer har en reference til
et Inner objekt, som er en del af det Outerobjekt, hvorfra det blev lavet. Læg mærke til at
Inner er en privat indre klasse. Det betyder i et og alt, at ingen klient af Outer selv kan instantiere
Inner. Læg også mærke til at Inner refererer til Outer's private a instans variabel.
|
|
|
Variationer over eksemplet Slide Note Contents Index References Speak | Inspireret af eksempelt på forrige side ser vi nu på en række variationer. Man kan måske sige at eksemplet udarter lidt. Dog kan man ved at studere detaljerne få styrket sin forståelse af Java's muligheder angående indre klasser. |
|
Program: Klassen Outer med en offentlig indre klasse Inner.
|
|
Program: En klient af Outer.
Vi ser at et indre objekt kan returneres fra det ydre objekt via metoden makeInner.
Det indre objekt holder fast i det ydre objekt, hvilket afsløres af udskriften 'inner outer'.
|
|
Program: Klassen Outer med en privat indre klasse Inner.
|
|
Program: En klient af Outer.
Vi ser igen at et indre objekt kan returneres fra det ydre objekt via metoden makeInner.
I klassen Application har vi imidlertid intet kendskab til klassen Inner, i det den er
private i Outer. Derfor bliver vi nødt til at erklære i af den generelle klasse Object.
På trods af dette får vi samme udskrift som i ovenstående variation: 'inner outer'.
Vi vil først forstå dette i detaljer når vi har studeret nedarvning og dynamisk binding.
|
|
Program: Klassen Outer med en offentlig indre klasse Inner.
|
|
Program: En klient af Outer som instantierer Inner i et Outer objekt.
I dette eksempel laves Inner objektet uden om fabrikations metoden i Outer.
Da Inner klassen er public kan vi instantiere Inner. Læg mærke til syntaksen
for dette, og i særdeleshed o objektets rolle i instantieringen. Dette understreger
at i skabes i o.
|
|
Lokale og anonyme klasser Slide Note Contents Index References Speak | Vi slutter af med at give et eksempel på en klasse som er lokal i en metode. |
|
Program: Klassen Outer med en lokal klasse Local i metoden method.
Eksemplet er helt igennem kunstigt. Det er svært at forestille en situation, hvor
noget lignende vil være nyttigt i praksis. Når vi senere får introduceret interfaces vil
det dog undertiden være nyttigt at lave lokale klasser som instantieres og returneres
til omverdenen. En sådan instans kan manipuleres via et interface.
Dette program udskriver tallet 45. Lad os forklare hvad der sker i programmet.
Hovedprogrammet main kalder den statiske metode method med 5 som parameter.
method laver en instans af den lokale klasse. Konstruktoren Local initialiserer
instVar til par + loc = 5 + 10 = 15. Bemærk at Local har tilgang til omkringliggende
lokale variable og parametre i method. (Disse skal dog af implementationstekniske
årsager være erklæret final - altså uforanderlige når først assignet).
Metoden methodLocal anvendt på instansen af Local returnerer nu 3*InstVar = 3*15 = 45.
method returnerer og instansen af Local forsvinder.
|
|
|
Chapter 4: Objekt-orienteret programmering i Java, del 2
Course home Author home About producing this web Previous lecture (top) Next lecture (top) Previous lecture (bund) Next lecture (bund)
Generated: March 31, 2008, 12:08:21