Kurt Nørmark ©
Department of Computer Science, Aalborg University, Denmark
September 2001
Abstract Previous lecture Next lecture Index References Contents | Nedarvning er en de definerende egenskaber af objekt-orienteret programmering. Vi tager i denne lektion udgangspunkt i hhv. specialisering og udvidelse, som vi bl.a. karakteriserer ved brug af ekstension og intension, som allerede blev introduceret i den første lektion på kurset. Dernæst indfører vi nedarvning som en programmeringssproglig mekanisme, der kan bruges til at implementere specialisering og udvidelse. Vi ser i slutningen af lektionen på polymorfi-begrebet i objekt-orienteret programmering, og herunder dynamisk binding der også kendt under betegnelsen 'virtuelle operationer' |
Specialisering og udvidelse |
Specialisering Slide Note Contents Index References Speak | Specialisering er en form for abstraktion hvormed vi danner et nyt begreb fra et eksisterende begreb. Vi vil nu gå over til også at tale om specialisering af klasser. Specialisering benyttes i en objekt-orienteret modelleringsproces |
|
The concept specialisering: En specialisering af en klasse A betegner en ny klasse B hvor
| Når vi specialiserer en klasse A danner vi en ny klasse som vi her vil kalde B. Mængden af B-objekter er en delmængde af A-objekterne. Ligeledes gælder at de operationer, som virker på objekter af typen A, også virker på objekter af typen B. Klassen B kan indeholde nye redefinerede operationer af A operationerne. Endvidere er det muligt og typisk, at klassen B definerer helt nye operationer i forhold til klassen A. De nye operationer i B relaterer sig til de specielle egenskaber, som B delmængden af A besidder. |
|
Eksempel på specialiseringer af Konto Slide Note Contents Index References Speak | Vi har i en tidligere lektion set på klassen Konto og en række mulige specialiserede kontoklasser. Vi vender her tilbage til eksemplet, specielt med henblik på at forstå is-a relationen |
Figure. Klassehierarkiet med Konto som den mest generelle klasse. Vi ser tre specialiserede kontoklasser: CheckKonto, AktionærKonto og GevinstKonto | ![]() |
Figure. Mulige ekstensioner af Konto klasserne. Vi ser her at en AktionærKonto er en (is a) Konto, og tilsvarende at en CheckKonto og en GevinstKonto er en (is a) Konto. | ![]() |
|
|
Specialisering og ekstension Slide Note Contents Index References Speak | Specialisering vil nu blive karakteriseret i forhold til begrebet 'ekstension' |
|
Figure. Ekstensionen af et begreb A indsnævres når klassen A specialiseres til klassen B | ![]() |
Is-a relationen mellem klasser kan måske lyde lidt abstrakt når vi taler om A og B klasser. De tilknyttede eksempler vil imidlertid gøre det mere klart, hvad det er vi mener |
|
|
Eksempel på specialiseringer af Figur Slide Note Contents Index References Speak | På denne side ser vi på et noget større hierarki, nemlig et hierarki af geometriske figurer |
Figure. Et specialiseringshierarki af geometriske figurer. Bemærk at en LigebenetRevinketTrekant både er en LigebenetTrekant og en RetvinkletTrekant. Dette lægger op til, at LigebenetRevinkletTrekant både arver fra LigebenetTrekant og RevinketTrekant | ![]() |
|
|
Udvidelse Slide Note Contents Index References Speak | Udvidelse af en klasse A med nye egenskaber er centralt fra et genbrugsperspektiv. Vi ønsker at holde klassen A intakt. I en ny klasse B ønsker vi at have alle egenskaber i A plus et antal nye egenskaber, som kun eksisterer i B. |
|
The concept udvidelse: En udvidelse af en klasse A betegner en ny klasse B som
| Når vi udvider en klasse A tilføjer vi nye instansvariable og metoder. Lad os kalde den nye udvidede klasse B. B har således alle A's egenskaber plus de nye 'udvidede egenskaber'. |
Udvidelse og intension Slide Note Contents Index References Speak | Parallelt med at vi ovenfor studerende specialisering i forhold til ekstensionsbegrebet vil vi nu se på udvidelse i forhold til intensionsbegrebet |
|
Figure. Intensionen af et begreb A bliver større når klassen udvides | ![]() |
|
|
Eksempel på udvidelse: Pair til Triple Slide Note Contents Index References Speak | Vi ser her på et konkret eksempel på to klasser, Pair og Triple, hvor Triple udvider Pair. |
Figure. Til venstre viser vi to klasser kaldet Pair og Triple. Triple udvider Pair med en ny part: part3. Vi har kun antydet operationerne på klasserne. Til højre ser vi to instanser af Pair og to instanser af Triple. Læg mærke til, at Triple instanser er hele objekter, på trods af klassen Triple er fremkommet ved at udvide klassen Pair | ![]() |
|
Nedarvning |
Nedarvning Slide Note Contents Index References Speak | Vi går nu over til at tale om 'nedarvning'. Som vi ser herunder, opfatter vi nedarvning som en udtryksform i programmeringssprog |
The concept nedarvning: Nedarvning er en programmeringssproglig udtryksform som afleder en ny klasse fra en eksisterende klasse | En klasse kan arve fra en anden klasse når vi programmerer i et objekt-orienteret programmeringssprog. Klassen som arver kan enten være en specialisering, en udvidelse, eller både en specialisering og en udvidelse af den oprindelige klasse |
|
Alternativ til nedarvning: Kopiering Slide Note Contents Index References Speak | På denne side ser vi på forskellen mellem at arve fra en klasse A og at udvide (en kopi) af klassen A. |
Figure. Til venstre illustrerer vi at klassen B er frembragt ved at kopiere A's egenskaber ind i en ny klasse B. Til højre har vi arrangeret os ved at lade klassen B arve fra A | ![]() |
|
Alternativ til nedarvning: Delegering Slide Note Contents Index References Speak |
The concept delegering: Ved delegering vil vi forstå at ét objekt videresender et givet arbejde til et andet objekt | Et objekt, som modtager en besked med et arbejde, det ikke selv kan/vil udføre, og som derfor videresender denne besked til et andet objekt, siges at delegere arbejdet. |
|
Figure. Et B-objekt, aB delegerer til et A-objekt, anA. | ![]() |
|
|
Nedarvning i Java Slide Note Contents Index References Speak | Angivelse af en klasses superklasse er lige til i Java. Vi viser her syntaksen |
Syntax: Syntaksen for definition af en klasse, som arver fra en anden klasse. Nøgleordet extends anvendes til at angive superklassen til en klasse i Java |
|
Figure. Den grafiske notation som modsvarer ovenstående skabelon for definition af en subklasse. Læg mærke til at pilen går fra subklassen til superklassen | ![]() |
Eksempel på nedarvning: CheckKonto Slide Note Contents Index References Speak | Vi har i en tidligere lektion set på klassen Konto. Her vil vi studere en specialiseret konto, som vi kalder CheckKonto |
Program: Java klassen CheckKonto som arver fra Konto.
Vi vender senere tilbage til detaljerne i konstruktoren samt anvendelsen af super i de
forskellige metoder i klassen - altså alle de blå aspekter i ovenstående. |
|
|
Checkkonto er både en udvidelse og en specialisering af Konto Slide Note Contents Index References Speak | Vi understreger her at nogle klasser både kan opfattes som en udvidelse og en specialisering af den oprindelige superklasse |
Figure. Vi gentager her nedarvningshierarkiet for klassen Konto | ![]() |
|
Exercise 7.1. Opgave om kvadrater i forhold til rektangler | Denne opgave skal ses i forlængelse af opgaven om rektangler fra en tidligere lektion. Lav en klasse Square (dansk: Kvadrat). Det er åbentlyst for alle, at der er et nært forhold mellem kvadrater og rektangler, men hvilket? Bør Rectangle arve fra Square, eller Square fra Rectangle? Overvej også om Square kan opfattes som en specialisering af Rectangle (eller omvendt). Eller vil det være mere givende at opfatte Rectangle som en udvidelse af Kvadrat (eller omvendt)? Implementer ud fra resultatet af disse overvejelser klassen Square. (Jeg linker her til min udgave af Rectangle incl. hjælpeklasser hvis I ønsker at tage udgangspunkt i denne). Klassen skal have 'passende konstruktorer' ala konstruktorerne fra Rectangle. Konstruktorerne i Square og Rectangle bør anvende hinanden via aktivering af super(....). Bortset fra konstruktorerne skal klassen Rectangle og Square ligne hinanden så meget som muligt. |
Eksempel på nedarvning: Triple Slide Note Contents Index References Speak | Tidligere i denne lektion så vi Triple som en udvidelse af Pair. Vi studerer nu disse to klasser i en Java implementation, som udnytter nedarvning |
Program: Java klassen Triple.
Som vi har set tidligere udvider Tripple klassen Pair. Vi ser her hvordan Triple arver fra Pair.
Vi vender tilbage til nogle af detaljerne senere i lektionen. |
|
|
Eksempel på nedarvning: DoubleLinkable Slide Note Contents Index References Speak | Linkable er klassen som implementerer de skjulte linkobjekter i kædede lister. Her ser vi på en udvidelse af Linkable, som også har en hægte til det foregående element. Vi ser altså på grundlaget for at kunne lave dobbeltkædede lister |
Program: Java klassen Linkable.
Instanser af klassen Linkable repræsenterer kædeobjekterne i en sammenkædet liste. | ![]() |
Program: Java klassen DoubleLinkable som arver fra Linkable.
Vi har udvidet klassen Linkable med en instansvariabel prev, som repræsenterer en hægte
til det foregående element i en dobbeltkædet liste |
|
Exercise 7.2. Dobbeltkædet cirkulær liste | Denne opgave skal ses i forlængelse af opgaven om cirkulære lister fra en tidligere lektion . I kan her vælge at fortsætte med løsning af opgaven om enkeltkædede cirkulære lister. Alternativt kan I læse videre og gennemføre denne opgave, som langt hen ad vejen kan opfattes som en designøvelse. I denne opgave bedes du designe en udvidelse af klassen CircularList, som var resultatet af opgaven fra lektion 5. (Jeg linker her til min udgave af CircularList for de af jer, som ønsker at tage udgangspunkt i denne). Udvidelsen består i at de cirkulære lister nu skal være dobbeltkædede. Lav en klasse DoubleCircularList som arver fra CircularList. Antag at klassen Linkable (hvis instanser er kædeobjekter) er en indre klasse til CircularList. DoubleCircularList bør tilsvarende indeholde en indre klasse, DoubleLinkable, som skal arve fra Linkable. Start med at lave den indre klasse DoubleLinkable i en tom klasse DoubleCircularList, og lav dernæst så meget af DoubleCircularList som tiden tillader. Læg vægt på følgende aspekter:
Jeg erindrer om, at vi faktisk smugkiggede på DoubleLinkable i forelæsningen . I kan naturligvis vælge at tage udgangspunkt i denne version af DoubleLinkable, og dermed gå mere direkte igang med programmering af DoubleCircularList. |
|
Instantiering og initialisering Slide Note Contents Index References Speak | På denne side studerer vi den generelle instantierings og initialiseringsproblematik når vi lader klasser arve fra hinanden. På næste side ser vi løsningen, som er valgt i Java |
|
En klasse D, der arver fra C som arver fra A, instantieres som ét objekt, der har alle egenskaber fra A, C og D. |
Figure. Et billede af et klassehierarki (til venstre) og en instans af klassen D til højre. Man skal bemærke at instansen af D er ét samlet objekt med A egenskaber, C egenskaber og D egenskaber. Tilsvarende er en instans af B ét samlet objekt med A egenskaber og B egenskaber. | ![]() |
|
Nedarvning og konstruktorer i Java Slide Note Contents Index References Speak | I direkte forlængelse problematikken identificeret herover ser vi nu på Java's løsning af initialiseringsproblemet. Vi ser også på en række Java eksempler på konstruktorer i de klasser vi introducerede ovenfor. |
En superklasse konstruktor er ikke direkte meningsfuld for subklassen. Derfor arves den ikke.
Men en konstruktor i superklassen løser dog typisk en del af problemet med at initialisere en instans af en subklasse.
Derfor vil det altid være tilfældet, at der aktiveres en superklasse konstruktor i forbindelse med initialisering af
en subklasse instans. Som det ses nedenfor har vi via super(...) mulighed for at angive hvilken af superklassens konstruktorer
vi ønsker anvendt. Reglen om, at konstruktorer ikke nedarves er typisk for objekt-orienterede sprog. Der er altså ikke blot tale om
en 'særhed' i Java |
Program: En skitse der viser hvordan en Java konstruktor i B kalder en konstruktor i superklassen A |
|
Program: Konstruktor i Java klassen CheckKonto som arver fra Konto. | ![]() |
Program: Konstruktor i Java klassen Triple. | ![]() |
Program: Konststruktorer i Java klassen DoubleLinkable som arver fra Linkable. | ![]() |
Grænseflader til klienter og subklasser i forbindelse med nedarvning Slide Note Contents Index References Speak | På denne side studerer vi den generelle grænsefladeproblematik ved nedarvning. Vi har ligesom i den simple situation (uden nedarvning) at gøre med grænsefladen til klienter. Men med introduktion af nedarvning kan vi nu også tale om grænsefladen mellem en klasse og dens subklasser |
Figure. De forskellige grænseflader for klasserne A og B:
| ![]() |
Nedarvning og synlighed i Java Slide Note Contents Index References Speak | Som allerede nævnt i tidligere lektioner har java en 'visibility modifier' som hedder protected. Det er denne modifier som er central i forbindelse med nedarvning |
|
The concept protected egenskab: En protected variabel eller metode i en klasse A kan ses i subklasser af A Protectede egenskaber er også synlige fra klasser i samme pakke som A. | Som en mellemting mellem 'private' og 'public' indfører vi nu protectede egenskaber af en Java klasse. Grundtanken er, at protectede egenskaber i en klasse kan ses direkte subklasser af klassen. I Java gælder endvidere, at protectede egenskaber også kan ses direkte fra alle andre klasser i samme pakke. Protectede egenskaber har altså også pakke synlighed |
Uden for A's pakke kan protectede egenskaber ses i objekter, der statisk er kvalificerede med mindst subklassen af A. Denne regel er omtalt nærmere i Java Tutorial samt i appendix F af Lewis and Loftus |
At Java tillader at gøre egenskaber mere offentlige betyder, at private egenskaber kan erklæres protected eller public i subklassen, og at protectede egenskaber kan erklæres public i subklassen At Java forbyder at gøre egenskaber mere private betyder i praksis, at protectede egenskaber ikke må gøres private, og at offentlige egenskaber ikke må gøres protectede eller private i en subklasse |
Program: Protectede instansvariable i Java klassen Konto. | ![]() |
Program: Protectede instansvariable i Java klassen Pair. | ![]() |
|
Forhindring af nedarvning i Java Slide Note Contents Index References Speak |
|
Klassehierarkier |
Nedarvning og dannelse af klassehierarkier Slide Note Contents Index References Speak |
|
|
Figure. Billeder svarende til de forskellige muligheder og begrænsninger mellem klasser, der arver fra hinanden. Situation (a) afspejler, at der er cykler, idet Z indirekte arver fra X, og X arver fra Z. Situation (b) er den normale og simple, hvor der dannes et træ. Situation (c) viser en acyklisk graf hvor V arver fra både Y og Z. I situation (d) arver Y to gange fra X. | ![]() |
Dannelse af klassehierarkier i Java Slide Note Contents Index References Speak | Vi ser nu på, hvordan et antal klassedefinitioner i Java kan definere et klassehierarki med klassen Object som rod |
|
|
Figure. En grov skitse af fire klasser i Java, der tilsammen danner et nedarvningstræ. Klassen A angiver ikke en superklasse, og den arver derfor implicit, men direkte fra Object. Klasserne B, C og D angiver alle en eksplicit, direkte superklasse (hhv. A, A, og C). Klasserne B, C og D arver således indirekte fra Object gennem A | ![]() |
|
Polymorfi og dynamisk binding |
Statiske og dynamiske typer Slide Note Contents Index References Speak | Vi indfører her et par definitioner på forskellige former for typer af variable og parametre mv. |
The concept statisk type: Den statiske type af en variabel eller parameter er den type, hvoraf variablen eller parameteren er erklæret | Den statiske type af en variabel er den type vi finder i variabelerklæringen | |
The concept dynamisk type: Den dynamiske type af en variabel eller parameter er typen af det objekt, variablen eller parameteren refererer til | Den dynamiske type er typen af det objekt, som variablen eller parameteren peger på via en reference |
Figure. To klasser A og B, hvor B arver fra A | ![]() |
Program: Erklæring af to variable x og y samt efterfølgende instantieringer og assignments |
|
Program: Et tilsvarende komplet Java program.
Programmet illustrerer samme situation som skitseret generelt ovenfor | ![]() |
Skelnen mellem statisk og dynamisk type af en variabel eller parameter er vigtig for at kunne forstå det nært beslægtede emne: statiske kontra dynamisk binding og virtuelle operationer. Vi vender tilbage til dette herunder. Det er også muligt og nyttigt at tale om den statiske hhv. den dynamiske type af et udtryk. Via typeerklæringer af variable, parametre og funktioners resultat kan man udtale sig om et udtryks statiske type. På næste side vil vi definere under hvilke omstændigheder de to assignments herover er lovlige. |
Polymorfi og typesammenlignelighed Slide Note Contents Index References Speak | Polymorfi er et nøglebegreb i mange programmeringssprog - objekt-orienterede såvel som sprog i andre paradigmer. Vi introducerer her polymorfibegrebet på det generelle plan. |
The concept polymorfi: Polymorfi betyder mangeformethed. Med polymorfi kan variable og parametre referere til objekter af mere end én type | Polymorfi hentyder til situationen hvor variable og parametre kan 'have eller antage forskellige former'. I programmeringssprog ser vi ofte, at polymorfe parametre afleder polymorfe procedurerer eller funktioner. Vi taler således om, at det er procedurerne eller funktionerne, der er polymorfe. Det simple polymorfibegreb på variable (og parametre) ses altså at kunne inducere et mere avanceret polymorfibegreb på procedurer og funktioner (og metoder). |
Figure. En scene hvor klassen B som sædvanlig arver fra klassen A. Vi ser endvidere en variabel v erklæret af typen A og en metode (i en ikke angivet kontekst) med en parameter af typen A. Det centrale for vores interesse er imidlertid lovligheden af assignmentet v = e og kaldet m(e), specielt hvad angår typen af udtrykket e i forhold til klassen A. | ![]() |
Dette er de væsentlige regler for typesammenlignelighed i Java, og en del andre objekt-orienterede programmeringssprog. |
De viste regler
udmærker sig ved, at de kan checkes på det tidspunkt programmet
oversættes. Årsagen til dette er, at der kun indgår statiske typer i
reglerne. Dette er en stor fordel, idet man så undgår relativt
kostbare checks på programmets udførelsestidspunkt. Lad os vende tilbage til de to assignments x = y og y= x fra forrige slide. Ifølge reglen indført på denne slide er x = y lovlig, idet den statiske type af y (nemlig B) er en subklasse af den statiske type af x (nemlig A). Igen ifølge reglen er y = x ulovlig. Årsagen er, at x´s statiske type (A) ikke er en subklasse af y´s statiske type (B). Når de to assignments forekommer i den viste rækkefølge, kan det føles restriktivt ikke at tillade y = x. Forskellige sprog har forskellige konventioner på dette punkt. Nogle sprog tillader y = x, og disse sprog følger således ikke de regler, vi har formuleret på denne slides. Sådanne sprog må ty til typecheck på programmets udførelsestidspunkt. |
Statisk typecheck er typecheck for programudførelsen starter; Det vil i praksis sige under compileringen. Når vi siger 'konservativ' mener vi her 'forsigtig' og 'garanterende'. Garantien skal sikre mod, at der ikke kan forekomme køretidsfejl som følge af typeproblemer. Når vi på køretidspunktet anvender en operation op på et objekt o gennem en variabel v (v.op(...)) ønsker vi at være sikre på, at op giver mening på det objekt (o), som v refererer. Statisk typecheck garanterer dette. |
Statisk og dynamisk binding Slide Note Contents Index References Speak | Dynamisk binding er en attraktiv og meget nyttig egenskab ved en objekt-orienteret programudførelse. Vi lader her op til til sondringen mellem statisk og dynamisk binding ved at studere to klasser, samt referencer til instanser af disse |
|
Figure. I denne scene, hvor B igen arver fra A, ser vi en operation op som er redefineret i B. Til venstre arrangerer vi os sådan, at variablen x med statisk type A får dynamisk type B. Spørgsmålet er om x.op(...) referer til op i A eller op i B | ![]() |
The concept dynamisk binding: Dynamisk binding: Den dynamiske type af x er bestemmende for bindingen af op | Når vi anvender dynamisk binding er det objektets type der afgør hvilken metode vi aktiverer | |
The concept statisk binding: Statisk binding: Den statiske type af x er bestemmende for bindingen af op | Når vi anvender statisk binding er det den statiske type den variabel, hvorigennem vi tilgår objektet der bestemmer metoden, som aktiveres |
Program: Et tilsvarende Java program.
Programmet illustrerer samme situation i Java, som skitseret generelt ovenfor | ![]() |
Hvis der anvendes statisk binding, kaldes op fra klassen A i
X.op(...). Omvendt, hvis der anvendes dynamisk binding, kaldes op fra
den specialiserede klasse B i X.op(...). I sprog med statiske typer (i programteksten) er det vigtigt, at anvendelse af dynamisk binding ikke svækker typesikkerheden. Sproget må derfor gennem de sproglige regler sikre, at uanset den dynamiske type af X, findes der en operation op, der kan anvendes. |
Statisk og dynamisk binding i Java Slide Note Contents Index References Speak | Betegnelsen 'virtuelle' operationer benyttes ofte i forbindelse med objekt-orienteret programmering. Vi sætter her denne betegnelse på plads i forhold til statisk og dynamisk binding |
|
|
|
Polymorfi og dynamisk binding i Banken Slide Note Contents Index References Speak | Vi viser her et eksempel på udnyttelse af klasserne Konto og CheckKonto, som illustrerer polymorfi |
Program: Superklassen Konto. | ![]() |
Program: Subklassen CheckKonto. | ![]() |
Program: Et hovedprogram som illustrerer dynamisk binding.
Vi laver 5 konti, som lagres i et array. Vi udnytter
polymorfien derved at arrayet kan referere både instanser af Konto og instanser af CheckKonto.
Læg særligt mærke til rentetilskrivningen, som foregår i en for-løkke. Carsten's checkkonto
får tilskrevet ubehagelig ågerrente, idet der er negativ saldo på kontoen. Den dynamiske binding
søger for, at den 'rigtige' rentetilskrivningsoperation bliver kaldt på de enkelte konti.
Udskrivningen af kontiene via toString metoden illustrerer også den dynamiske binding. Kør
selv programmet, og verificer at der er tale om dynamisk binding af rentetilskrivningsoperationen. |
|
Eksemplet uden dynamisk binding Slide Note Contents Index References Speak | Her viser vi eksemplet fra forrige side uden anvendelse af dynamisk binding |
Diskrimination af objekter betyder at gøre forskel på objekter. Forskellen består i i hvilken operation der bliver kaldt når der sendes en bestemt besked. |
Program: Bank programmet uden anvendelse af fordelene ved dynamisk binding.
|
|
Program: Superklassen Konto med operationen tilskrivRenteKonto | ![]() |
Program: Subklassen CheckKonto med operationen tilskrivRenteCheckKonto | ![]() |
Fordele ved dynamisk binding Slide Note Contents Index References Speak | Vi ser her på fordelene ved at have dynamisk binding. Som en kontrast så vi allerede på forrige side et eksempel på, hvordan man begår sig uden dynamisk binding |
|
Metode redefinition og -kombination |
Redefinition af metoder og variable Slide Note Contents Index References Speak | Når man laver en subklasse er der ofte behov for at redefinere egenskaber fra superklassen. I Java gøres dette simpelthen ved at definere egenskaber i subklassen, som har samme navne eller signaturer, som egenskaberne i superklassen |
|
The concept redefinition: En metode eller variabel i en klasse B siges at være redefineret hvis der findes en metode eller variabel af samme navn i B's superklasse | I subklassen af en klasse kan vi overskrive superklassens egenskaber. På denne måde kan vi - i forbindelse med nedarvning og dannelsen af en subklasse - redefinere allerede eksiterende egenskaber |
|
Program: Et kunstigt program som illustrerer redefinition af variable og metoder, og dynamisk binding af metoder.
Vi skaber et B objekt, aB, hvortil der sendes beskeden m(7). På grund af
dynamisk binding kaldes B's m metode, som assigner v i B til 7. Metoden m
i A kaldes dernæst med 7-3=4 som parameter. Som følge af dette bliver v i A
assignet til 4. Objektet aB printes, hvilket forårsager at this.v (i B) og
super.v (i A) udskrives. Programmet's output bliver:B: this.v = 7, super.v = 4 |
|
Program: En let ændring af ovenstående som illustrerer at redefinerede variable bindes statisk.
Variablen v findes i både A og B klassen. Vi aflæser v gennem aB1 og aB2 variablene.
Dette kan vi gøre da v variablene i A og B er protectede, og dermed også klasse- synlige.
Den første er erklæret af typen A, den anden af typen B.
Udskriften er 'Variablen v gennem A kvalificeret variabel: 5. Variablen v gennem B kvalificeret variabel: 6'.
Vi ser altså at der ikke udnyttes dynamisk binding ved tilgang af variable, men derimod statisk binding.
|
|
Vi ser på denne generelle problemstilling på næste side |
Forhinding af redefinition Slide Note Contents Index References Speak |
Vi har tidligere omtalt final metoder, og disse kan selvsagt ikke redefineres i subklasser. Private egenskaber kan ikke ses uden for klassen, og man kan derfor ikke med god mening tale om, de kan redefineres. |
Program: Metoden m, som er privat i A, forsøges redefineret som en offentlig metode.
Dette giver ikke god mening, idet m i A ikke kan ses fra B. Når vi således
i B's m metode kalder super.m(...) får vi en fejl fra compileren.
|
|
Varians af parametre og returværdi under redefinition Slide Note Contents Index References Speak |
|
Figure. En situation hvor klassen B arver A, og hvor T arver fra S. Typerne S og T anvendes som typer i parametre på metoder i hhv. A og B klasserne | ![]() |
Program:
En praktisk anvendelse af klasserne A, B og S som typisk skaber problemer i objekt-orienteret programmering, men ikke i Java |
|
Vi kalder operationen op på et objekt af typen B. Dette objekt er refereret gennem en variabel, der er erklæret af (har statisk type A). Ud fra et statisk synspunkt er det derfor OK at overføre et S-objekt til operationskaldet. På grund af dynamisk binding vil vi her antage, at operationen op i klassen B kaldes. Dette er en tidsindstillet bombe, idet op fra B kan kalde en T-operation på sin parameter. Kald af en T-operation på et S-objekt er klart meningsløst. Hvad skal der til for at 'demontere' den tidsindstillede bombe? Et run-time check på, at (i vort tilfælde) x faktisk refererer til et T-objekt. For mange run-time checks gør programmer langsomme. Derfor strør compiler-skrivere ikke om sig med sådanne. |
Covarians og contravarians Slide Note Contents Index References Speak | Her vil vi introducere to navne for de to grundliggende måder parametre kan variere i redefinerede metoder |
The concept covarians: Covarians: Typer af operationsparametre varierer på samme måde, som de klasser, hvori operationerne befinder sig. | Covarians betyder, at parametre af metoder varierer på samme måde (i samme retning) som de omkringliggende klasser | |
The concept contravarians: Contravarians: Typer af operationsparametre varierer på modsat måde, som de klasser, hvori operationerne befinder sig. | Contravarians er det modsatte af covarians |
Exercise 7.3. Opgave om covarians | Forklar hvorfor der ikke opstår problemer i forbindelse med covarians i det Java program, som blev omtalt på den tilknyttede slide |
Metodekombination Slide Note Contents Index References Speak | Når en redefineret metode samarbejder med den 'overskrevne' metoder kalder vi det undertiden for metodekombination. Vi vil her se på forskellige måder at styre 'kombinationen' |
Figure. En klasse B arver fra klassen A. B redefinerer metoden 'op' fra A. | ![]() |
|
Vi tænker her konkret på, at en metode i subklassen B kan aktivere metoden af samme navn i superklassen A ved super.op(...) |
Terminologi |
Nedarvningsterminologi Slide Note Contents Index References Speak | Vi runder af med en oversigt over den forskelligartede nedarvningsterminologi, der findes i udvalgte objekt-orienterede programmeringssprog |
|
Figure. To klasser A og B, hvor B arver fra A | ![]() |
Table. Forskellig terminologi for nedarvning i forskellige objekt-orienterede programmeringssprog |
|
Chapter 7: Nedarvning
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:47