Læringsmål for forelesningen • Objektorientering – Arv
• Javaprogrammering – Arv i Java
• Eclipse – Undersøke klassehierarki i Eclipse
1
Arv (eng: inheritance) • Er en fundamental OOmekanisme • Arv gir muligheten til definere nye klasser, basert på eksisterende – vi kan utvide eksisterende klasser – spesialisere eksisterende klasser
• En slik såkalt subklasse, arver alle egenskapene til superklassen
– instanser av subklassen vil inneholde alle felt og metoder (inkl. konstruktører) deklarert i både superklassen og subklassen – alle grensesnitt arves, dvs. garanti for implementerte metoder – alle public og protectedfelt og metoder deklarerert i superklassen, kan refereres til i subklassens kode
2
Hvorfor arv? • Klassifisering i klassehierarkier er en intuitiv organisering av fenomener i verden
pattedyr hovdyr
– hovdyr er et pattedyr – katt og hund er et rovdyr er et pattedyr – gnager er et pattedyr
rovdyr
katter
gnagere
hunder
• Arv gir mulighet for gjenbruk av kode • Forenkler strukturering av komplekse problemer og programmer • 3
Mange mener at arv må støttes for at et programmeringsspråk skal være “ekte” objektorientert
Exception Exceptionhierarki RuntimeEx.
IOEx. FileNotFoundEx.
4
IllegalArgumentEx.
NullPointerEx.
NumberFormatEx.
IndexOutOfBoundsEx.
StringI.O.O.B.Ex.
ArrayI.O.O.B.Ex.
http://www.falkhausen.de/en/diagram/html/java.util.Collection.html 5
Lynkurs i arv
Object
• Klasser struktureres i et hierarki, f.eks. C1 C2 C1, C11, C12, C2, C21, C22 • Et objekt laget som C21 C22 C11 C12 en instans av en peker på superklassen klasse C, er instanceof C og alle C sine C21 c21 = new C21(); superklasser 6
c21 instanceof C2 = = true
Typisk to typer bruk av arv • Spesialisering av eksisterende klasse(r) – noen har allerede laget en eller flere klasser i et hierarki, og vår subklasse skal spesialisere den som passer best – eksempler: • Exception/RuntimeException • JComponent/JPanel
• Vi lager vårt eget klassehierarki, med tett koblede klasser – superklasse Bok, subklasser Ordbok og Tegneseriealbum
7
Spesialisering/subklassing av eksisterende klasse(r) • Utgangspunkt: – Eksisterende klassehierarki – Andre klasser som bruker klassene i hierarkiet på en veldefinert måte
• Eksempler: – Object, +operatoren og OutputStream/Writerklassene – Exception/RuntimeException og unntakssystemet – JComponent/JPanel og Swing 8
Object, +operatoren og OutputStream/Writerklassene • Object
– implisitt superklassen til alle klasser – definerer en del metoder, inkl. String toString(), som alle klasser forventer at finnes
• +operatoren baserer seg på at toStringmetoden kan brukes for å lage en tekstlig representasjon av et objekt – ”hei” + obj betyr omtrent ”hei”.concat(obj.toString())
• OutputStream/Writerklassene baserer seg på toString metoden
– når en skriver ut objekter, så vil toStringmetoden bli brukt til å konvertere objektet til tekst
• Ved riktig redefinering av toString() så vil vår egen (Objectsub)klasse gli pent inn i Java sin objekttiltekst konverteringsmekanisme 9
Redefinering av toString() • public class Person { private String name; public String toString() { return ”[Person ” + name + ”]”; } } #1: Person
Objectdel Persondel
• 10
String toString() { ... } boolean equals(Object) { ... } String toString() { ... } String name =
Person har nå to toString()-metoder, men kun den i subklassen er synlig utenifra – –
en metode i en subklasse skygger for en metode med samme navn og parametre i superklassens subklassen kan referere til superklassens ved bruk av super.toString()
Exception/RuntimeException og unntakssystemet • throw, catch og throws forventer en Exception instans – throw new IllegalArgumentException(...) – catch (IllegalArgumentException iae) – throws IllegalArgumentException
• Viktig distinksjon mellom checked og unchecked exceptions: – RuntimeException og subklassene er unchecked – Exception og andre subklasser er checked
• Ved riktig bruk av subklassing (visse regler må overholdes) så vil vår egen (Runtime)Exception subklasse gli pent inn i Java sitt unntakssystem 11
NameValidationException • Person har en setNamemetode og regler for hvilke tegn som tillates i et navn • Hvis reglene ikke overholdes, så skal det kastes en ny type unntak: NameValidationException • NameValidationException lagrer informasjon om det nye (ulovlige navnet) og Personobjektet • Ved å subklasse riktig Exception(sub)klasse, så vil vår klasse blir brukt av unntakshåndteringsmekanismen på ønsket måte – checked eller unchecked – riktig logiske klassifisering
12
NameValidationException •
public class NameValidationException extends IllegalArgumentException { private Person person; private String illegalName;
}
public NameValidationException(Person person, String illegalName) { this.person = person; this.illegalName = illegalName; } public String getMessage() { return illegalName + ” is an illegal name for ” + person; }
#1: NameValidationException
Object del
String toString() { ... }
Ill.Arg.Exc. del
String toString() { ... } String getMessage() { ... } String getMessage() { ... }
NameVal.Exc.del 13
Person person = String name =
Hierarchyview •
Hvordan ser objektet vårt ut?
•
Velg klassenavnet og trykk F4
#1: NameValidationException
Object del
String toString() { ... }
Ill.Arg.Exc. del
String toString() { ... } String getMessage() { ... } String getMessage() { ... }
NameVal.Exc.del 14
Person person = String name =
Sekvensdiagram #1: NameValidationException
1: toString() // Throwable sin metode 1.1: getLocalizedMessage() // Throwable sin metode 1.1.1: getMessage() // NameValidationException sin metode
• Ved å redefinere riktig metode kan vi skyte vår egen kode inn i en kallsekvens på strategisk riktig sted • Dette krever at vi forstår hvordan superklassen bruker sine egne metoder 15
JComponent/JPanel og Swing • JComponent er en generell GUIelementklasse • JComponent har en del paintmetoder som kalles av Swing for å tegne innholdet i GUIelementet – public void paint(Graphic g) kaller
• protected void paintBorder(Graphics g) • protected void paintComponent(Graphics g) • protected void paintChildren(Graphics g)
• Med subklassing og redefinering av riktig paint metode så kan vi lage våre egne GUIelementer
16
Sekvensdiagram #1: JComponent 1: paint() 1.1: paintComponent 1.2: paintBorder
paint kaller paintComponent paintBorder paintChildren
1.3: paintChildren
17
• paintComponent er den som er ”riktigst” å redefinere, siden paint gjør viktig håndtering av Graphicsobjektet og paintBorder ikke trenger å endres på.
Redefinering av metoder i Eclipse
18
MyComponent, alt. 1 • liste av firkanter, som tegnes i en løkke
19
MyComponent, alt. 2 • liste av firkanter, som tegnes i en løkke • utnytter at – Graphicsargumentet alltid er en Graphics2D, som kan litt mer – En Rectangle er en Shape, som kan brukes som argument til Graphics2D sin drawmetode
20
Eget klassehierarki, med tett koblede klasser • En bok har en tittel • Ordbøker og tegneseriealbum er bøker – Bok er et generelt begrep, med sine felter – En ordbok er en spesiell type bok
• lar Ordbokklassen arve egenskaper fra Bokklassen • definerer i tillegg feltet antallOrd
– Et tegneseriealbum er også en bok • lar Tegneseriealbumklassen arve egenskaper fra Bokklassen • definerer i tillegg feltet antallStriper 21
Ordbok og Tegneseriealbum arver fra Bok • Ordbok – extends Bok, arver dermed tittelfeltet – definerer også eget antallOrdfelt
• Tegneseriealbum – extends Bok, arver dermed tittelfeltet – definerer også eget antallStriperfelt 22
Definere subklasse • Ny klasse Ordbok • Bok er superclass
23
• Legger til extends Bok
Begreper knyttet til arv • Vi sier at Bok er superklassen til Ordbok og Tegneseriealbum, mens Ordbok og Tegneseriealbum er subklasser av Bok • Ordbok og Tegneseriealbum er spesialiseringer av Bok Bok String tittel • Bok er en generalisering av Ordbok og Ordbok Tegneseriealbum Tegneseriealbum int antallOrd
24
int antallStriper
Instanser og klassetilhørighet • Et objekt instansieres av én bestemt klasse • Objektet har alle egenskaper definert i denne klassen og (alle) dens superklasse(r)
25
#1: Bok tittel = ”Sofies verden” #2: Ordbok tittel = ”Riksmålsordboken” antallOrd = 32768
– #1 er en Bok og har feltet tittel Ordbokdel – #2 er en Ordbok og har Bokdel feltene tittel og antallOrd #2: – #3 er et Tegneseriealbum og har Tegneseriealbum feltene tittel og tittel = ”Flat firer” antallStriper antallStriper = 128 Tegneseriealbumdel
Instanser og klassetilhørighet • Vi kan si at et objekt også er en X, dersom X er (en av) superklassen(e) – #1 er Bok, #2 er både Ordbok og Bok og #3 er både Tegneseriealbum og Bok
• Arving av egenskaper sikrer at Ordbokobjekter og Tegneseriealbum for alle praktiske formål er Bokobjekter
Bokdel 26
Tegneseriealbumdel
#1: Bok tittel = ”Sofies verden” #2: Ordbok tittel = ”Riksmålsordboken” antallOrd = 32768
Ordbokdel #2: Tegneseriealbum tittel = ”Flat firer” antallStriper = 128
Instanser i Eclipse • Sette breakpoint • Kjøre i debugmodus • Boksubklasser har tittel felt og felt definert i egen klasse 27
Arv av metoder (1) • En subklasse arver alle egenskaper til superklassen – felter – vanlige metoder – konstruktører arves ikke direkte, men kan brukes av subklassens konstruktør
• Metodene som arves fra en superklasse, kan kun bruke felt som er definert i superklassen 28
– f.eks. vil get og setmetoder i Bok virke som før, de leser og setter felter i Bokdelen av en Ordbok
Arv av metoder (2) • Flere metoder vi har brukt er egentlig arvet – toStringmetoden, som alle objekter har, er egentlig arvet fra java.lang.Object – assertXXXmetodene, som en finner i JUnittestene til JExercise, er arvet fra TestCaseklassen i JUnitrammeverket
• Dersom en definerer samme metode i en subklasse, vil denne brukes istedenfor den i superklassen, jfr. egendefinerte toString metoder • Vi sier at en metode som er redefinert i en subklasse, skygger for den i superklassen 29
Arving og redefinering av toStringmetoden Run
• Redefinerer toString i Bokklassen: Run
• Redefinerer toString i Ordbokklassen: Run 30
Typer, referanser og instanser (1) • To måter å tenke på typer og variabler, parametre, felter og returverdier – Typen garanterer hva objektet den refererer til har av egenskaper – Typen begrenser hva slags objekt den kan ha som verdi
• Typen til en variabel/felt avgjør hvilke felt og metoder det er tillatt å bruke
– Dersom bokaMi er deklarert som Bok, vil bokaMi.tittel være lov, men ikke bok.antallStriper, selv om bokaMi faktisk refererer til en Tegneseriealbuminstans
31
Typer, referanser og instanser (2) • For å kunne garantere at et objekt har de nødvendige egenskapene, må en også begrense hva en variabel/felt kan referere til – Dersom bokaMi er deklarert som Ordbok, kan den ikke referere til (dvs. tilordnes) et objekt som kun er en Bok.
• En variabel/felt deklarert av type X kan referere til objekter av type Y, dersom Y er X eller subklasse av X
– En Bokvariabel/felt kan referere til Bok, Ordbok og Tegneseriealbumobjekter, mens en Objectvariabel/felt kan referere til alle type objekter!
• Siden Y har arvet alle egenskapene til X, sikrer det at Y har de garanterte evnene
– En Ordbokinstans kan for alle praktiske formål brukes som en Bokinstans, siden alle Ordbokinstanser har alle Bokegenskapene
32
Typer, referanser og instanser (3) • instanceofoperatoren ( instanceof ) sjekker om er av en bestemt klasse, uavhengig av typen til uttrykket • Tabellen viser hvilke objekter som gir true for hvilke typer: – Object o1 = new Bok(); – Object o2 = new Ordbok(); – Object o3 = new Tegneseriealbum();
instanceof
33
o1: Bok
o2: Ordbok
o3: Tegneserie
instanceof Object
?
?
?
instanceof Bok
?
?
?
instanceof Ordbok
?
?
?
instanceof Tegneseriealbum
?
?
?
Typer, referanser og instanser (3) • instanceofoperatoren ( instanceof ) sjekker om er av en bestemt klasse, uavhengig av typen til uttrykket • Tabellen viser hvilke objekter som gir true for hvilke typer: – Object o1 = new Bok(); – Object o2 = new Ordbok(); – Object o3 = new Tegneseriealbum();
instanceof
34
o1: Bok
o2: Ordbok
o3: Tegneserie
instanceof Object
true
true
true
instanceof Bok
true
true
true
instanceof Ordbok
false
true
false
instanceof Tegneseriealbum
false
false
true
instanceof og casting • instanceof brukes typisk for å sjekke at bruk av et objekts spesifikke felter og metoder er lov: – Bok bok = new Ordbok(); ... if (bok instanceof Ordbok) { System.out.println(bok.getAntallOrd()); } • •
Vi vet at koden er logisk grei, men det er likevel ikke lov, siden typen til bok fortsatt ikke kan garantere at objektet har getAntallOrdmetoden Etter å ha testet typen til et objekt, må vi bruke ”casting” for å garantere overfor Java at objektet har den nødvendige typen, før egenskapen brukes:
• if (bok instanceof Ordbok) { System.out.println(((Ordbok)bok).getAntallOrd()); } 35
instanceof og casting • Casting tvinger Java til å akseptere at en objekt(referanse) er av annen (mer spesialisert) type enn deklarasjonen garanterer
– Casting til subklasse kalles downcasting, som er det mest vanlige – Casting til superklasse kalles upcasting, som en sjelden gang kan være nyttig
• objekt kan castes til X dersom objekt instanceof X er true, ellers får en ClassCastException 36
Hva vil det altså si å arve? • En klasse definerer egenskaper, i form av felter og metoder, som instansene vil få • Ved arving/subklassing vil alle egenskapene definert i superklassen også gjelde for subklassen • Ekstra egenskaper definert i subklassen legges til de som er definert i superklassen 37
Hva med innkapsling? • Innkapslingsprinsippet gjelder fortsatt. • En ny synlighetsmodifikator: protected innføres for å definere hvilke egenskaper i superklassen som blir synlige i subklassene 38
Synlighet av arvede egenskaper • Arv krever introduksjon av en ny grad av synlighet, mellom public og private • Egenskaper markert som protected i en superklasse er synlige kun i subklassene
– felter markert med protected kan både leses og endres i subklassen – metoder markert med protected kan både kalles og redefineres i subklassen
• Merk forskjellen mellom synlighet og eksistens:
– et privatefelt er ikke synlig i subklassens kode, men finnes fortsatt – en privatemetode er ikke synlig i subklassens kode, men finnes fortsatt og kan kalles indirekte via synlig metoder
39
Synlighet av arvede egenskaper • NB! protectedegenskaper skaper en tettere og ofte uønsket binding mellom super og subklasser – protected skal brukes i tilfeller hvor direkte tilgang til superklassens egenskaper er nødvendig – metoder som det er meningen/naturlig at skal redefineres i subklasser bør markeres som protected – felter bør kun i nødsfall markeres som protected 40
Innkapsling og arv klasse Methods Client, med tilgang til public metoder
Egenskaper markert med protected er synlig i subklassen
subklasse Methods
41
Data
Data
Mer om redefinering av metoder (eng: overriding) • Ved subklassing arves både felter og metoder. • Arv av metoder gjør det mulig å bruke superklassens metoder på instanser av en subklasse
– toStringmetoden definert i Object kan brukes på alle instanser av alle klasser – getTittelmetoden definert i Bok kan brukes på alle Ordbokinstanser
• Dersom en ønsker å erstatte en arvet metode med en egen implementasjon, defineres bare en metode med samme synlighet, returverdi og parameter i subklassen – Bok kan definere en alternativ toStringmetode med signaturen public String toString(), som setter sammen relevante Bokfelter
42
Redefinering av metoder • Redefinerte metoder skygger for arvede, slik at metoden definert i subklassen kalles istedenfor den i superklassen – Bok sin toStringmetode blir brukt istedenfor den som er arvet fra Object
• Hvilken metode som kalles er avhengig av klassen som objektet er laget av, ikke typen til referansen – Ordbok ordbok = new Ordbok(); // kaller toString-metoden definert i Ordbok System.out.println(ordbok); Bok bok = ordbok; // kaller fortsatt toString-metoden definert i Ordbok System.out.println(bok);
43
Object objekt = bok; // kaller fortsatt toString-metoden definert i Ordbok System.out.println(objekt);
Redefinering av metoder • Det er det faktiske objektet som avgjør hvilken metode som velges, ikke typen til uttrykket, men typen til uttrykket begrenser hvilke metoder som kan brukes • Skygging av metoder kan imidlertid være problematisk... 44
Legger til valideringskode i Bok sin setTittelmetode • Sjekker om tittelen inneholder ulovlige bokstaver
• Det er viktig at subklasser ikke omgår denne sjekken, men er med på å sikre at reglene for Bok sin oppførsel følges 45
Oppgave: Definer en alternativ setTittelmetode for Ordbok, som sikrer at tittelen til en Ordbok slutter på ”ordbok” Sjekker om tittel slutter på ”ordbok” og i tilfelle ikke, legger til ”ordbok” 46
Alternativ setTittelmetode • Redefinerer setTittel i Ordbokklassen: – samme signatur som setTittel i Bokklassen – sjekker endelsen og legger evt. til ”ordbok”endelsen
• To problemer:
– tittelfeltet må være protected og ikke private, for at Ordbok sin setTittelmetode skal kunne endre tittelfeltet – Bok sin setTittelmetode inneholder egen valideringskode, som burde vært duplisert i Ordbok sin setTittelmetode
• Forslag til løsning? 47
Ved redefinering av en metode i en subklasse, hadde det vært fint å kunne bruke superklassen sin metode, slik at en slipper å duplisere kode (og logikk) Java gir oss muligheten til å kalle metoder i superklassen fra en subklasse, selv disse er redefinert i subklassen 48
super.<metode>(...) konstruksjonen • Med super som prefiks kan en kalle en metode i superklassen, selv om denne er redefinert i subklassen! • Dette løser begge våre problemer
– vi kan deklarere tittelfeltet som private, siden vi kan sette den vha. Bok (altså superklassen) sin setTittelmetode – vi kan kalle Bok sin setTittelmetode med en evt. endret tittel, og være sikker på at denne valideres iht. Bok sine egne regler
• Merk at super.<metode>(...)
– kan kalles fra alle metoder i subklassen, ikke bare fra <metode> – kun kan brukes for å kalle metoder definert i den direkte superklassen, og ikke metoder i supersuperklassen
49
• thisreferansen vil være den samme
super gjør det mulig å (gjen)bruke superklassens metoder, selv om de redefineres i subklassen Det er som om Ordbok består av én Bok eller superdel og én egen Ordbokdel, og super gir mulighet til å referere til metoder i superdelen 50
super del egen del
#1: Ordbok ... void setTittel(String) super
... void setTittel(String)
Redefinering av konstruktører • En konstruktør er en spesiell metode som kalles ifm. initialisering av en nyopprettet instans. • super(...) MÅ brukes for å kalle superklassens konstruktør, slik at en sikrer at også superdelen blir riktig og skikkelig initialisert. • super(...) MÅ stå først i konstruktøren, for å sikre at superklassens felter initialiseres før subklassens! • I Bokklassen:
– initialiserer tittelfeltet
• I Ordbokklassen:
51
– kaller superklassen sin konstruktør – initialiserer antallOrdfeltet – alternativt kunne en fjernet antallOrdparametret og initialiseringen av det, men konstruktøren MÅ defineres
Kallsekvens • mainmetode – lager en Ordbokinstans og endrer tittelen
52
Redefinering vs. overlasting (overriding vs. overloading) • Redefinering
– Metoder med like parameterlister (og returtyper) i ulike super og subklasser – Hvilken faktisk instans metoden kalles på, avgjør hvilken metode som kalles – Metoden som kalles avgjøres dynamisk ved utførelsen
• Overlasting
– Metoder med ulike parameterlister (antall og type), som ikke har annet felles enn navnet. – Hvilken metode(variant) som kalles, avgjøres av den deklarerte typen til parametrene – Metoden som kalles avgjøres statisk ved kompilering
• Ved kombinasjon av overlasting og redefinering
– først brukes de deklarerte typene til parameterlista tilsvarende overlasting – deretter kalles den mest spesifikke metoden på instansen
53
Konstruktører kan også overlastes • Flere konstuktører med ulike parameterlister kan defineres • En konstruktør kan kalle en annen definert i samme klasse med this(...) • this(...)konstruksjonen er analogt med bruk av super(...): Den navnløse konstruktørmetoden i egen (this) eller superklassen (super) kalles • NB! Dersom en konstruktør må kalle en annen, må dette skje i første linje!!! 54
Læringsmål for forelesningen • Objektorientering – Arv
• Javaprogrammering – Arv i Java
• Eclipse – Undersøke instanser i Eclipse
55