Kurt Nørmark ©
Department of Computer Science, Aalborg University, Denmark
September 2001
Abstract Previous lecture Next lecture Index References Contents | I denne lektion vil vi studere mekanismer i det objekt-orienterede paradigme, som retter sig mod design af klassehierarkier. Som sædvanlig ser vi både på emnet generelt og specifikt i forhold til Java. Abstrakte klasser og ikke mindst klassehierarkier med abstrakte klasser er et meget relevant emne i forhold til denne lektion. Java's interface begreb vil også blive gennemgået. Endvidere vil vi kort tangere mulighederne og problemerne med multipel nedarvning, samt sætte dette i forhold til Java's brug af interfaces |
Abstrakte klasser |
Abstrakte klasser Slide Note Contents Index References | Abstrakte klasser anvendes når vi skal designe de mest generelle dele af et klassehierarki. Der skal defineres subklasser af abstrakte klasser for at nyttiggøre disse. Vi vil her introducere de generelle begreber og ideer. På de efterfølgende sider vil vi se på Java detaljerne. |
|
The concept abstrakt klasse: En abstrakt klasse er en klasse med abstrakte metoder | En abstrakt klasse er en klasse, som foruden 'normale metoder' også indeholder én eller flere forudannoncerede metoder, uden krop | |
The concept abstrakt metode: En abstrakt metode er en særligt markeret metode uden krop | En forudannonceret metode er markeret med modifieren 'abstract' | |
The concept forudannoncering: En abstrakt metode siges også at være forudannonceret | ||
The concept konkret klasse: En ikke-abstrakt klasse kaldes undertiden for en konkret klasse | Klasser som ikke er abtrakte vil undertiden blive kaldt konkrete klasser. Ligeledes bruges denne terminlogi for metoder |
Da abstrakte klasser mangler detaljer i kroppen af abstrakte metoder giver det ikke mening at instantiere klasserne. Hvis vi gjorde det, kunne vi ikke opererere på dem. |
|
|
Eksempel: Stack Slide Note Contents Index References | Det første eksempel vi ser på er den velkendte Stack udsat for abstrakte klasser |
|
Program: Den abstrakte klasse Stack.
Klassen indeholder en række abstrakte metoder samt to konkrete metoder, hvoraf den
mest bemærkelsesværdige er toggleTop. Metoden toggleTop ombytter de to øverste elementer
på stakken, forudsat naturligvis at stakken har mindst to elementer. Ved brug af push, pop og top operationerne kan
vi implementere toggleTop på det abstrakte niveau. Metoden toggleTop arves naturligvis af alle konkrete subklasser
af den abstrakte Stack.
|
|
Abstrakte klasser: Skematisk eksempel Slide Note Contents Index References | Efter at have set på et konkret eksempel på en abstrakt klasse vil vi her skitsere et hierarki af abstrakte og konkrete klasser. |
Figure. En grafisk skitse af et klassehierarki, hvor C arver fra B som arver fra A. Kursive navne henviser til abstrakte klasser og metoder. På figuren er de røde metoder abstrakte, og de blå er ikke-abstrakte. A og B er abstrakte klasser. Dog er B 'lidt mere konkret' end A, idet operationen Q i B er defineret fuldt ud. B er abstrakt idet B ikke har defineret den abstrakte metode P, som arves fra A. C er en konkret klasse, hvori både P og Q er fuldt ud definerede operationer. Endvidere er der kommet en ny operation S til. | ![]() |
Abstrakte klasser i Java Slide Note Contents Index References | Vi vil nu introducere abstrakte klasser i forhold til Java |
Syntax: Syntaksen for definition af en abstrakt klasse. På dette niveau er er den eneste syntaktiske forskel, at 'modifieren' abtract er benyttet. |
|
Abstrakte klasser, som ikke har abstrakte metoder, kan naturligvis (heller) ikke instantieres Når vi siger, at en abstrakt klasse i Java kan afledes fra en konkret klasse mener vi at en subklasse kan være abstrakt selv om den's superklasse er konkret. Dette kan måske bruges til i et stort klassehierarki at introducere niveauer mellem konkrete klassser, som vi vil forhindre instantiering af |
Abstrakte metoder i Java Slide Note Contents Index References | I forlængelse af ovenstående introducerer vi her abstrakte metoder i forhold til Java |
|
Syntax: Syntaksen for definition af en abstrakt metode. Bemærk, at vi kun angiver metodehovedet. Der er altså ingen krop i { ... } i en abstrakt metode |
|
Eksempel: Stakken igen Slide Note Contents Index References | Vi vender her tilbage til stak eksemplet. Vores primære ærinde er at se på en konkret specialisering af den abstrakte klase Stack. |
Program: Den abstrakte klasse Stack igen.
| ![]() |
Program: En konkret specialisering af Stack uden øvre begrænsning, baseret på klassen Vector.
De grønne dele er nytilføjede data i klassen. Den abstrakte klasse havde ingen data erklæringer overhovedet.
Den brune del implementerer konstruktorern for UnboundedStack.
De blå dele implementerer de abstrakte metoder.
Den lilla del redefinerer toString metoden.
|
|
Program: Et eksempel på en anvendelse af klassen UnboundedStack.
Programmet udskriver 'Stack: 3.1.' svarende til at toppen af stakken er
3, og 'bunden' er 1.
|
|
Eksempel: Comparable Slide Note Contents Index References |
Program: Den abstrakte klasse Comparable.
Givet at subklasser af Comparable definerer lessThan, som er abstrakt i Comparable,
bidrager klassen med konkrete metoder for lessThanOrEqual, greaterThan og
greaterThanOrEqual. Denne blanding af abstrakte og konkrete metoder
udgør en stærk mulighed, når vi arbejder med abstrakte klasser.
|
|
I ovenstående klasse giver det kun mening at sammenligne to objekter af samme klasse. Dette sikres ikke i den viste klasse. Statisk set er der intet til hinder for at sammenligne et bankkonto objekt med en cirkulær liste, forudsat at begge er Comparable. Dette er utilfredsstillende, og det giver ikke mening. Det ville have været værdifuldt at kunne udtrykke, at typen af parameteren (af f.eks. lessThan) skal være af samme type som det objekt, hvorpå lessThan aktiveres. Eiffel, som er stærk inden for multipel nedarvning, tilbyder en sådan mulighed (idet typen af en parameter kan angives som 'like Current') |
Exercise 8.1. Sammenlignelige bankkonti | I forelæsningen studerede vi en abstrakt klasse Comparable, der definerer en ordning på objekter som er instanser af (subklasser af) Comparable.
(Det er kun intentionen at kunne sammenligne objekter i samme klasse. Som bemærket i forelæsningsnoterne er dette svært at
sikre statisk i Java). Definer nu et Java Interface Comparable, som svarer til den abstrakte klasse Comparable. Interfacet Comparable skal altså have fire operationer: lessThan, lessThanOrEqual, greaterThan og greaterThanOrEqual. Afprøv interfacet Comparable ved at definere en specialisering af klassen Konto, som implementerer interfacet Comparable. Specialiseringen skal hedde CompKonto. Vi antager at en konto k1 er mindre end k2 hvis saldoen af k1 er mindre end saldoen af k2. Specielt er kontoen k1 er lig med k2 (k1.equals(k2)) hvis de indeholder det samme beløb. Redefiner i den forbindelse equals i den nye Konto klasse. Afprøv den specialiserede Konto klasse i et simpelt hovedprogram, som laver to Konto objekter og sammenligner disse med hinanden. Da mange sikkert ikke har tid til at lave et hovedprogram selv, kan I vælge at benytte mit hovedprogram. Dermed består opgaven altså I at lave interfacet og en Konto specialisering, som implementerer interfacet. |
Eksempel: Microbib Slide Note Contents Index References | Vi vil her diskutere dele af et eksempelprogram, som organiserer litteratur i et klassehierarki. |
Figure. Hierarkiet af litteratur i microbib eksemplet, illustreret med OOD notation ala UML. Klasserne Book, Journal (dk: tidsskrift) og Article arver fra en abstrakte klasse Literature. en Article er endvidere en del af en Journal. Et LiteratureCollection objekt er en container, som består af Literature | ![]() |
|
Program: Den abstrakte klasse Literature.
Vi har fremhævet de aspekter som har med metoderne printitem og match at gøre. | ![]() |
Program: Den konkrete subklasse Book af Literature.
| ![]() |
Program: Klassen LiteratureCollection.
I denne klasse fokuserer vi på anvendelsen af print og match fra Literature klassehierarkiet.
| ![]() |
Multipel nedarvning |
Hvorfor multipel nedarvning? Slide Note Contents Index References | Vi vil indledningsvis overveje, hvorfor man kunne ønske sig at arve fra to eller flere klasser i et objekt-orienteret program |
|
|
Problemstillinger ved multipel nedarvning Slide Note Contents Index References | Vi så kort i forrige lektion at en klasse kan arve fra mere end én klasse i nogle objekt-orienterede programmeringssprog. Vi vil nu se lidt nærmere på dette, og vi vil identificere nogle af de problemer og udfordringer, der opstår i den sammenhæng. |
Figure. En situation hvor navnet x arves af C fra både A og B | ![]() |
Lad os først understrege at de fire problemstillinger hænger ganske tæt sammen. Når vi taler om navnesammenfald som et problem er det ud fra en filosofi om, at et navn kun kan referere til én egenskab (én routine og/eller én instansvariabel). Hvis flere egenskaber har samme navn er det tvetydigt, hvilken egenskab vi egentlig mener. Som et alternativ til at løse navnesammenfaldsproblemet kan man forsøge at løse kombinationsproblemet. Filosofien er nu at vi refererer til begge (alle) egenskaber i en eller anden kombination. Kunststykket er naturligvis så at finde ud af, hvordan man generelt, eller for bestemte slags egenskaber, kan danne kombinationer. |
Multipel klassificering Slide Note Contents Index References | Der findes ikke en entydig klassificering af objekters egenskaber. Herunder viser vi et eksempel på flere forskellige klassificeringer af objekter. Da disse overlapper bliver der behov for at lave klasse (og objekter) som er placeret i det overlappende felt. Dette leder umiddelbart til et behov for multipel nedarvning |
Figure. Klasserne C1 og C2 illustrerer behovet for at kunne arve fra to eller flere klasser, som på overlappende vis klassificerer den totale mængde af objekter i et objekt-orienteret system. Flere af ovenstående klasseficeringer findes i Java, dog ikke som klasser, men som Interfaces | ![]() |
|
Multipel nedarvning: Fornuftsægteskab Slide Note Contents Index References | Vi ser her på en form for multipel nedarvning, hvor vi dels arver fra en abstrakt klasse, dels fra en meget konkret klasse. |
Figure. En situation hvor FixedStack arver fra hhv. Stack og Array | ![]() |
Program: Skitse af FixedStack som kan friste til multiple nedarvning (kan ikke oversættes).
De med blåt fremhævede steder i programmet viser de steder, hvor der anvendes egenskaber
fra Array (som vi her forestiller os, at vi har arvet fra). Som bekendt findes denne
klasse ikke direkte i Java klassebiblioteket.
|
|
|
Interfaces |
Interface begrebet Slide Note Contents Index References | Vi starter vores behandling af interfaces med et overordnet 'kig' på interface begrebets egenskaber |
|
The concept interface: Et interface er en klasse-lignende samling af erklæringer uden egentlig 'substans' Et interface indeholder ikke variable eller metoder med kroppe | Et interface (ala Java) er en samling af metode specifikationer og konstant definitioner. Med en metode specifikation mener vi en metode uden krop, også kaldet en metode signatur |
Hvis man i en klasse C implementerer to interfaces, som indeholder samme konstant, vil der være en konflikt. Denne konflikt forhindrer at C kan oversættes. Andre konflikter eksisterer ikke |
Interface i Java: Syntaktiske regler Slide Note Contents Index References | Vi ser her på de syntaktiske regler for definition af Interfaces (med og uden super interfaces), samt for hvorledes en klasse kan angive, at den implementerer et interface |
Syntax: Et interface er en navngivning mængde af konstant og metode-signatur erklæringer |
|
En klasse kan påtvinges at skulle implementere én eller flere interfaces, og samtidig arve fra én superklasse: |
Syntax: En klasse, som arver fra en superklasse, kan endvidere implementere en eller flere interfaces, her interfaceNavn1 og interfaceNavn2 (og evt. flere på de tre prikkers plads) |
|
Et interface kan udvide én eller flere andre interfaces: |
Syntax: Et interface kan udvide én eller flere interfaces |
|
Interfaces i Java: Semantiske regler Slide Note Contents Index References | I kølvandet på de syntaktiske regler nævnt ovenfor observerer vi her en række mere semantiske regler omkring brugen af interfaces i Java |
|
Eksempel: StringInput og StringOutput Slide Note Contents Index References | Ideen med disse interfaces er primært at givet eksempler på erklæring af rimelig realistiske interfaces i Java. |
|
Program: Interfacet StringInput. |
|
Program: Interfacet StringOutput.
Bemærk at metoden toStringRepresentation svarer helt til metoden toString() i klassen Objekt. |
|
Program: Interfacet StringInputOutput som udvider både StringInput og StringOutput |
|
Eksempel: StringInput og StringOutput Slide Note Contents Index References | Vi viser her hvordan StringInput og StringOutput interfacene kan anvendes. Lad os understrege, at eksemplet udelukkende er tænkt illustrativt i forhold til en demonstration af interfaces; eksemplet er ikke godt nok gennemført til at være praktisk brugbar (og der er næppe i Java behov for de metoder, som Interfacet specificerer) |
Program: En klasse IoKonto som implementerer interfacet StringInputOutput.
Metoderne i interfacet skal defineres i klassen IoKonto. Vi har vist et simpelt eksempel på, hvordan det kan gøres. |
|
Program: Et eksempel på en klasse som anvender IoKonto.
|
|
|
Interfaces i Java Core API: Enumeration Slide Note Contents Index References | Interfaces anvendes i udstrakt grad i Java bibliotekterne. Vi ser her nærmere på et antal eksempler, første Enumeration |
|
Program: Interfacet Enumeration som det er defineret i Java biblioteket i pakken java.util, og strippet for
en stor mængde af javadoc kommentarer |
|
|
Exercise 8.2. Iterator i cirkulær liste | Denne opgave bygger endnu engang videre på opgaven om cirkulære lister,
som vi har set på nogle gange under øvelserne i dette kursus. Det er naturligvis muligt at tage udgangspunkt
i løsningen på denne opgave, enten jeres egen eller min løsning. Udvid klassen CircularList med en operation elements, der returnerer en iterator for en cirkulær liste. Iteratoren skal være et objekt, der implementerer interfacet Enumeration. Det er tilladt at antage, at der ikke indsættes elementer i listen under et gennemløb. Afprøv jeres nye CircularList klasse ved at gennemløbe en liste med brug af iteratoren. |
Interfaces i Java Core API: Cloneable Slide Note Contents Index References |
|
Det forårsager en undtagelse (exception) hvis man sender besked clone til et objekt, hvis klasse ikke implementerer interfacet Cloneable (hvis klassen ikke har signaleret, at det er OK at clone). |
Program: Klassen Point defineret som cloneable.
Klassen Point fra pakken java.awt kan ikke clones. (Eller kan den - den's superklasse java.awt.geom.Point2D kan faktisk clones).
Derfor definerer vi her en triviel subklasse af java.awt.point, som kan clones |
|
|
Interfaces i Java Core API: Serializable Slide Note Contents Index References | Interfacet Serializable fra pakken java.io formidler 'letvægts persistens' af objekter i Java. Med termen 'letvægts persistens' hentyder vi til forskellen mellem faciliteten beskrevet her og en egentlig database løsning, som mere direkte er i stand til at lagre persistente objekter (en objekt-orienteret database) |
|
Program: Et programfragment som gemmer et objektnetværk på en binær fil.
Det viste programfragment udskriver et array objekt literatureShelf, som er en instans af klassen LiteratureCollection (tidligere diskuteret i denne lektion).
|
|
Program: Et programfragment som reetablerer et objektnetværk fra en binær fil.
Dette programfragment indlæser objekterne, som blev udskrevet af programfragmentet vist ovenfor.
|
|
|
|
Interfaces i forhold til abstrakte klasser Slide Note Contents Index References | Interfaces og abstrakte klasser er beslægtede. Her vil vi se hvorledes slægtskabet kan beskrives |
|
Hvis man skulle tale om et 'ultimativ superinterface' skulle det være et Interface som var fuldstændigt tomt |
|
Interfaces på tværs af klasser Slide Note Contents Index References | Vi vil her markere en stærk pointe ved interfaces i kombination med klassebegrebet |
|
|
|
Interfaces i forhold til klasser med multipel nedarvning Slide Note Contents Index References | Vi har kaldt interfaces for 'fattigmands multipel nedarvning'. Dette er sandt et stykke hen ad vejen, men interfaces bidrager også som en abstraktionsmekanisme, der 'går på tværs' af klassehierarkiet |
|
Chapter 8: Design af klassehierarkier
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:54