IN1010 våre 2019 Osdag 6. februar Arv og subklasser - del 2 Stei Gjessig
Dages tema Virtuelle metoder som er det samme som Polymorfi Når bruker vi arv / år bruker vi komposisjo Kostruktører i subklasser Virtuelle Polymorfi - fie av, me det er ikke så vaskelig 2
Klassehierarki: Persobil Bil Repetisjo: Subklasser class Bil { <lys beige egeskaper> class Persobil exteds Bil { <røde egeskaper> class Lastebil exteds Bil { < grøe egeskaper> class Drosje exteds Persobil { < gule egeskaper> Alle lastebiler Lastebil Drosje Alle biler Alle drosjer Alle persobiler 46 objekter 46 ew 3
class Bil { protected it pris; public it skatt( ) {retur pris * 0.25; Polymorfi: eksempel Klassehierarki: Bil class Persobil exteds Bil { protected it atallpassasjer; public it skatt( ) {retur pris * 1; Persobil class Lastebil exteds Bil { protected double lastevekt; public it skatt ( ) {retur pris * 0.5; Lastebil class Drosje exteds Persobil { protected Strig loyveid; public it skatt ( ) {retur pris * 0.25; Drosje 4
Polymorfi: eksempel class Bil { protected it pris; public it skatt( ) {retur pris * 0.25; class Persobil exteds Bil { protected it atallpassasjer; public it skatt( ) {retur pris * 1; protected it pris public it skatt( ) {retur pris*0.25; protected it pris public it skatt( ) {retur pris*0.25; protected it atpassasjer public it skatt( ) {retur pris * 1; class Lastebil exteds Bil { protected double lastevekt; public it skatt ( ) {retur pris * 0.5; protected it pris public it skatt( ) {retur pris*0.25; private double lastevekt public it skatt( ) {retur pris*0.5; class Drosje exteds Persobil { protected Strig loyveid; public it skatt ( ) {retur pris *0.25; protected it pris public it skatt( ) {retur pris*0.25; protected it atpassasjer public it skatt( ) {retur pris * 1; protected Strig loyveid public it skatt( ) {retur pris*0.25; Bilobjekt Persobilobjekt Lastebilobjekt Drosjeobjekt 5
Polymorfi: eksempel Bil protected it pris public it skatt( ) {retur pris*0.25; Bil Persobil Bil Lastebil Bil Persobil Drosje protected it pris public it skatt( ) {retur pris*0.25; protected it atpassasjer public it skatt( ) {retur pris * 1; protected it pris public it skatt( ) {retur pris*0.25; private double lastevekt public it skatt( ) {retur pris*0.5; protected it pris public it skatt( ) {retur pris*0.25; protected it atpassasjer public it skatt( ) {retur pris * 1; protected Strig loyveid public it skatt( ) {retur pris*0.25; Bilobjekt Persobilobjekt Lastebilobjekt Drosjeobjekt 6
Bil Bil Persobil Bil Lastebil b1 Polymorfi: eksempel b2 p1 b3 last protected it pris 100000 public it skatt( ) {retur pris*0.25; protected it pris 200000 public it skatt( ) {retur pris*0.25; protected it atpassasjer public it skatt( ) {retur pris * 1; Bilobjekt Persobilobjekt Hva blir: Bil Persobil Drosje b4 p2 d1 protected it pris 480000 public it skatt( ) {retur pris*0.25; private double lastevekt public it skatt( ) {retur pris*0.5; Lastebilobjekt b1.skatt() p1.skatt() b2.skatt() last.skatt() b3.skatt() b4.skatt() p2.skatt() d1.skatt() 25000 200000 200000 12000 12000 80000 80000 80000 protected it pris 320000 public it skatt( ) {retur pris*0.25; protected it atpassasjer public it skatt( ) {retur pris * 1; protected Strig loyveid public it skatt( ) {retur pris*0.25; Drosjeobjekt 7
Omdefierig av metoder - polymorfi Vi har sett at med subklasser ka vi utvide e eksisterede klasse med ye metoder (og ye variable) E subklasse ka også defiere e metode med samme sigatur som e metode i superklasse, me med ulikt ihold. De ye metode vil omdefiere (erstatte) metode som er defiert i superklasse Metoder som ka omdefieres på dee måte kalles virtuelle metoder I Java er alle metoder virtuelle, så sat de ikke er deklarert med fial Virtuelle metoder = polymorfi 8
Polymorfi: Nytt eksempel For objekter av type ValigHud er det class ValigHud { dee metode som //... gjelder. public void bjeff() { System.out.pritl("Vov-vov"); class Rasehud exteds ValigHud { //... public void bjeff() { For objekter av type Rasehud er det dee metode som gjelder. System.out.pritl("Voff-voff"); ValigHud Rasehud
Polymorfi: eksempel ValigHud v Rasehud r ValigHud g public void bjeff() { System.out.pritl("Vov-vov"); public void bjeff() { System.out.pritl("Vov-vov"); public void bjeff() { System.out.pritl("Voff-voff"); Ata dette programmet: Hva skrives ut ved hvert av kallee: ValigHud v = ew ValigHud(); Rasehud r = ew Rasehud(); ValigHud g = r; v.bjeff(); r.bjeff(); g.bjeff(); Vov-vov Voff-voff Voff-voff 10
Istrumet ist void skrivdefiisjo() { System.out.pritl( Et istr..."); Oppgave: Hva skrives ut år programmet Musikk.java kjøres? void skrivdefiisjo() { System.out.pritl( Et piao... "); class Musikk { public static void mai (Strig[] args) { Istrumet ist = ew Piao(); ist.skrivdefiisjo(); class Istrumet { public void skrivdefiisjo () { System.out.pritl ("Et istrumet er oe ma ka spille på"); class Piao exteds Istrumet { public void skrivdefiisjo () { System.out.pritl ("Et piao er et stregeistrumet"); Istrumet Piao 11
Musikk versjo 2 Hva skjer i dette tilfellet? Istrumet ist void skrivdefiisjo( ) { System.out.pritl( Et istrum..."); void skrivdefiisjo(strig overskrift) { System.out.pritl(... ); System.out.pritl( "Et piao.. ); class Musikk { public static void mai (Strig[] args) { Istrumet ist = ew Piao(); ist.skrivdefiisjo(); class Istrumet { public void skrivdefiisjo () { System.out.pritl("Et istrumet er oe ma ka spille på"); class Piao exteds Istrumet { public void skrivdefiisjo (Strig overskrift) { System.out.pritl(overskrift); System.out.pritl("Et piao er et stregeistrumet"); 12
Istrumet ist void skrivdefiisjo(strig overskrift) { System.out.pritl(... ); System.out.pritl( "Et istrumet.. ); Musikk versjo 3 void skrivdefiisjo( ) { System.out.pritl( Et piao..."); class Musikk { public static void mai (Strig[] args) { Istrumet ist = ew Piao(); ist.skrivdefiisjo(); class Istrumet { public void skrivdefiisjo(strig overskrift) { System.out.pritl(overskrift); System.out.pritl("Et istrumet er oe ma ka spille på"); Hva skjer a? Programmet lar seg ikke oversette class Piao exteds Istrumet { public void skrivdefiisjo () { System.out.pritl("Et piao er et stregeistrumet"); 13
Musikk-eksemplee: Lærdom Når vi ser på et objekt via e superklasse-peker, mister vi valigvis tilgag til metoder og variable som er defiert i subklasse. Dersom e metode i subklasse også er defiert (med samme sigatur) i superklasse har vi likevel tilgag via superklasse-pekere, fordi objektets dypeste metode brukes. Slike metoder kalles virtuelle metoder, og dee mekaisme kalles polymorfi. Det som er relevat er derfor hvilke metoder som fies i superklasse (med hvilke parametre), me ikke ødvedigvis iholdet i metodee. Samme sigatur = samme av og øyaktig samme parametre (ikke ikl. returtype i Java, me Java protesterer hvis gal returtype) 14
Flere virtuelle metoder class Vare { protected it pris; public void setpris(it p){pris = p; protected it prisutemoms() { retur pris; public it prismedmoms() { retur (it) (1.25*prisUteMoms()); class SalgsVare exteds Vare { protected it rabatt; // I proset... public void setrabatt(it r){ rabatt = r; protected it prisutemoms() { retur pris (pris*rabatt/100); 15
pris 100 Vare v = ew Vare(); v.setpris(100); SalgsVare s = Vare v2 ew SalgsVare(); s.setpris(100); s.setrabatt(20); Vare v2 = s; SalgsVare s Hva blir å: v.prismedmoms(); s.prismedmoms(); v2.prismedmoms(); Vare v protected it prisutemoms ( ) { retur pris; public it prismedmoms { retur (it) (1.25*prisUteMoms ( ) ); pris protected it prisutemoms ( ) { retur pris; public it prismedmoms { retur (it) (1.25*prisUteMoms ( ) ); rabatt 100 20 protected it prisutemoms ( ) { retur pris (pris*rabatt/100); 16
Polymorfi: skrivdata I uiversitets-eksemplet så vi at klassee Studet og Asatt (før vi hadde lært om subklasser) hadde este like skrivdata-metoder: // I klasse Studet: public void skrivdata() { System.out.pritl("Nav: " + av); System.out.pritl("Telefo: " + tlfr); System.out.pritl("Studieprogram: " + program); // I klasse Asatt: public void skrivdata() { System.out.pritl("Nav: " + av); System.out.pritl("Telefo: " + tlfr); System.out.pritl("Løstri: " + løstri); System.out.pritl("Timer: " + atalltimer); 17
Nøkkelordet super Nytt Nøkkelordet super brukes til å aksessere variable / metoder i objektets superklasse. Dette ka vi bruke til å la superklasse Perso ha e geerell skrivdata, som så kalles i subklassee: // I klasse Perso: public void skrivdata() { System.out.pritl("Nav: " + av); System.out.pritl("Telefo: " + tlfr); // I klasse Studet: public void skrivdata() { super.skrivdata(); System.out.pritl("Studieprogram: " + program); // Tilsvarede i klasse Asatt: public void skrivdata() { super.skrivdata(); System.out.pritl("Løstri: " + løstri); System.out.pritl("Timer: " + atalltimer); 18
class StudetRegister { public static void mai(strig [] args) { Studet stud = ew Studet(); Perso pers = ew Perso(); stud.skrivdata(); pers.skrivdata(); // Her brukes defiisjoe i Studet // Her brukes defiisjoe i Perso Perso pers Perso pers2 = stud; pers2.skrivdata(); // Hvilke defiisjo beyttes her? Studet stud Perso pers2 void skrivdata() { System.out.pritl("Nav: " + av); System.out.pritl("Telefo: " + tlfr); void skrivdata() { System.out.pritl("Nav: " + av); System.out.pritl("Telefo: " + tlfr); Regel: Det er objekttype, ikke referasetype, som avgjør hvilke defiisjo som gjelder år e metode er virtuell. void skrivdata() { super.skrivdata(); System.out.pritl("Studprgm: " + prgm); 19
20 Omdefierig av variable E subklasse ka også omdefiere (skyggelegge) variable som er defiert i superklasse. MEN: Dette bør IKKE brukes!!! Sjelde ødvedig Reduserer lesbarhete Ka føre til uvetet oppførsel Og mer treger dere ikke å vite om det
Klassehierarki: Et eksempel fra Java-biblioteket ArrayList AttributeListt RoleList RoleUresolvedList Oppgave: Slå opp på ArrayList i Javabiblioteket og se at de tre klassee er direkte subklasser av ArrayList (direkte aboer i klassehierarkiet) ( Direct Kow Subclasses )
Klassehierarki: Også fra Java-biblioteket: Feil-klasser Object Throwable Error Exceptio Virtual- Machie- Error IOError RutimeExceptio IOExceptio Oppgave: Slå opp i Javabiblioteket AWTExceptio... og ca. 60 adre
Repetisjo: De boolske operatore istaceof hjelper oss å fie ut av hvilke klasse et gitt objekt er, oe som er yttig i mage tilfeller: class TestFrukt { public static void mai(strig[] args) { Eple e = ew Eple(); skrivut(e); static void skrivut(frukt f) { if (f istaceof Eple) System.out.pritl("Dette er et eple!"); else if (f istaceof Appelsi) System.out.pritl("Dette er e appelsi!"); Frukt class Frukt {.. class Eple exteds Frukt {.. class Appelsi exteds Frukt {.. Eple Appelsi 23
Me: Prøv å ugå istaceof Istedefor å teste hvilke klasse objektet er av, be objektet gjøre jobbe selv: Bedre program: class TestFrukt2 { public static void mai(strig[] args) { Fruk2 f = ew Eple2(); f.skrivut( ); abstract class Frukt2 { abstract public void skrivut( ); Bruk heller polymorfi hvis mulig class Eple2 exteds Frukt2 { public void skrivut( ) { System.out.pritl("Jeg er et eple!"); class Appelsi2 exteds Frukt2 { public void skrivut( ) { System.out.pritl("Jeg er e appelsi!"); 24
god Biler og mer bruk av istaceof HashMap <Strig, Bil> h; (og litt castig (typekoverterig)) h = ew HashMap <Strig, Bil> ( ); h... for (Bil b: h.values()) { Strig r = b.regnr; // kall på virtuell metode: b.skatt( ); if (b istaceof Persobil) { Persobil pb = (Persobil) b; it pas = pb.hetatpass(); else { if (b istaceof Lastebil) { Lastebil ls = (Lastebil) b; double lv = ls.hetlastevekt(); class Bil { Strig regnr; public void skatt(){... class Persobil exteds Bil { it atpass; public void skatt(){... class Lastebil exteds Bil { double lastevekt; p.. void skatt(){... class Drosje exteds Persobil { it LøyveNr; p.. void skatt(){... 25
Oppgave Brev Ata at vi har deklarasjoee Sokad class Brev { class Sokad exteds Brev { class Kjaerlighetsbrev exteds Brev { Avgjør hvilke av følgede uttrykk som er lovlige: Kjaerli Lovlig Ulovlig Sokad s1 = ew Sokad(); Sokad s2 = ew Brev(); Brev b1 = ew Sokad(); Brev b2 = (Brev) ew Sokad(); Sokad s3 = ew Kjaerlighetsbrev(); Sokad s4 = (Sokad) ew Kjaerlighetsbrev(); Brev b3 = (Sokad) ew Brev(); 26
Hvorfor bruker vi subklasser? 1. Klasser og subklasser avspeiler virkelighete Bra år vi skal modellere virkelighete i et datasystem 2. Klasser og subklasser avspeiler arkitekture til datasystemet / dataprogrammet Bra år vi skal lage et oversiktlig stort program 3. Klasser og subklasser ka brukes til å forekle og gjøre programmer mer forstålig, og spare arbeid: Gjebruk av programdeler Bottom up programmerig Lage verktøy Top dow programmerig Nå skal vi se litt på 3 Postulere verktøy 27
Gjebruk av deler av programmer Viktig å ikke måtte skrive y kode hver gag ma skal programmere oe ytt Gjebruk mest mulig av kode du har skrevet før Lag kode med heblikk på et de skal brukes (til oe likede) seere Lag biblioteker Bruk adres bibliotek Javas eget bibliotek Strukturerig av kode ( gjebruk i samme program) IN1000: Gjebruk av metoder og klasser 28
Gjebruk ved hjelp av klasser / subklasser Ved sammesetig (komposisjo) (i Oblig 1, pesum i IN1000): Deklarer referaser til objekter av klasser du har skrevet før (eller biblioteksklasser) Lag objekter av disse klasse Kall på metoder i disse klassee Ved arv (ytt i IN1010): Lag e y klasse som utvider de eksisterede klasse (spesielt viktig ved litt større klasser) Føy til ekstra variable og metoder 29
Gjebruk ved sammesetig / komposisjo Omtret som i oblig 1. Ikke oe ytt class Demoklasse { HashMap<Strig,Perso> veer = ew HashMap<Strig,Perso>(); Husdyr h = ew Hud( Passopp ); Strig av = Ole-Morte"; /* + Diverse metoder */ veer, h og av er deklarert som referasevariable som peker på objekter av adre klasser som allerede eksisterer. h veer av Ole-Morte 30
Gjebruk ved arv (domeet er et bibliotek) Objekter av klassee class Bok { protected Strig tittel, forfatter; class Fagbok exteds Bok { protected double dewey; class Skjølitterærbok exteds Bok { protected Strig sjager; class Bibliotek { Bok b1 = ew Fagbok(); Bok b2 = ew Skjølitterærbok(); Arv Komposisjo Gjebrukes Gjebrukes 31
Når skal vi bruke arv? Geerelt: Ved er-e relasjo mellom objektee. E Studet er e Perso E Asatt er e Perso Hva med relasjoee roma bok? E roma er e bok (arv). kapittel bok? Et kapittel er ikke e bok, me et kapittel er e del av e bok, og e bok har/består av kapitler (sammesetig) Relasjoer som har-e og består-av skal ikke modelleres som subklasser, me ved hjelp av sammesetig (som datafelt (kostater/variable)). Arv vs. delegerig 32
Oppgave Hvor er det aturlig å bruke komposisjo og hvor er det aturlig med arv i disse tilfellee? Relasjo mellom Komposisjo Arv vare - varelager yhetskaal - kaal perso - persoregister cd - spor (sager) PC - datamaski gaupe - rovdyr fly - trasportmiddel motor - bil 33
Object: tostrig og equals Klasse Object ieholder bl.a. tre viktige metoder: Strig tostrig() returerer e Strig-represetasjo av objektet boolea equals(object o) sjekker om to objekter er like (i Object det samme som pekerlikhet) it hashcode( ) returerer e hash-verdi av objektet Disse metodee ka ma så selv redefiere til å gjøre oe mer foruftig. Poeget er at e bruker av e klasse vet at disse metodee alltid vil være defiert (pga. polymorfi) 34
Eksempel på tostrig og equals class Pukt { protected it x, y; Pukt(it x0, it y0) { x = x0; y = y0; Ata: class Pukt2 { protected it x, y; Pukt2(it x0, it y0) { x = x0; y = y0; public Strig tostrig() { retur ("x = "+x+" y = "+y); Pukt p1 = ew Pukt(3,4); Pukt p2 = ew Pukt(3,4); Pukt2 q1 = ew Pukt2(3,4); Pukt2 q2 = ew Pukt2(3,4); Hva blir å: public boolea equals(object o) { if (!(o istaceof Pukt2)) retur false; Pukt2 p = (Pukt2) o; retur x == p.x && y == p.y; p1.tostrig(); p1.equals(p2); Pukt@f5da06 false q1.tostrig(); q1.equals(q2); x = 3 y = 4 true 35
Kostruktører Ikke oe ytt Bruk av kostruktører år vi opererer med "ekle" klasser er gaske ukomplisert. Når vi skriver Pukt p = ew Pukt(3,4); skjer følgede: class Pukt { protected it x, y; 1. Det settes av plass i iter-miet til et objekt av klasse Pukt og til referasevariable p. 2. Variablee x og y blir opprettet ie i objektet (istasvariable) 3. Kostruktør-metode blir kalt med x0=3 og y0=4. 4. Etter at kostruktøre har satt x=3 og y=4, blir verdie av høyreside i tilordige Pukt p = ew Pukt(3,4) adresse (e referase, peker) til det ye objektet. 5. Tilordige Pukt p = utføres, dvs p settes lik adresse / referase til objektet. av: p type: Pukt Pukt(it x0, it y0) { x = x0; y = y0; Pukt(it x0, it y0) av: x0 3 type: it av: x x = x0; y = y0; type: it av: y0 4 type: it av: y 3 4 type: it 36
Kostruktører og arv Det blir oe mer komplisert år vi opererer med arv: Ata at vi har defiert e subklasse class B exteds A { Hvilke kostruktør utføres hvis vi skriver B bpeker = ew B(); Kostruktøre i klasse A? Kostruktøre i klasse B? Begge? B A bpeker A() B() B 37
Kostruktører og arv (forts.) Nytt Ata at vi har deklarert tre klasser: class A { class B exteds A { class C exteds B { Når vi skriver ew C() skjer følgede: 1. Kostruktøre til C kalles (som valig) 2. Kostruktøre til C starter med å kalle på B si kostruktør 3. Kostruktøre til B starter med å kalle på A si kostruktør 4. Så utføres A si kostruktør 5. Kotrolle kommer tilbake til B si kostruktør, som utføres 6. Kotrolle kommer tilbake til C si kostruktør, som utføres 38
Kall på super-kostruktøre Nytt Superklasses kostruktør ka kalles fra e subklasse ved å si: super(); - vil kalle på e kostruktør ute parametre super(5, test ); - om vi vil kalle på e kostruktør med to parametre (it og Strig) Et kall på super må legges helt i begyelse av kostruktøre. Kaller ma ikke super eksplisitt, vil Java selv legge i kall på super( ) helt først i kostruktøre år programmet kompileres. Hvis e klasse ikke har oe kostruktør, legger Java i e tom kostruktør med kallet super(); 39
NB! Det er forskjell på super. og super(...)
Eksempel 1 Ata at vi har følgede klasser: class Perso { proteceted Strig fødselsr; Perso() { fødselsr = 12034567890"; class Studet exteds Perso { protected it studid; Studet() {... Ata to kostruktører: Studet() { super(); studid = 0; eller: Studet() { studid = 0; Disse to er helt ekvivalete! Hva skjer hvis Studet ikke har oe kostruktør :? class Studet exteds Perso { it studid = 0; Svar: det går bra 41
Eksempel 2 Her er fire forslag til kostruktører: Studet() { studid = 0; Ata at vi har følgede klasser: class Perso { protected Strig fødselsr; Perso(Strig fr) { fødselsr = fr; class Studet exteds Perso { protected it studid; Studet() {... Studet() { super( 12345"); studid = 0; Studet(Strig r){ super(r); studid = 17; Studet(Strig r, it id){ super(r); studid = id; Hvilke virker? Diskuter! 42
Eksempel 3 class Bygig { Bygig() { System.out.pritl("Bygig"); class Bolighus exteds Bygig { Bolighus() { System.out.pritl("Bolighus"); Hva blir utskrifte fra dette programmet? class Blokk exteds Bolighus { Blokk() { System.out.pritl("Blokk"); public static void mai(strig[] args) { ew Blokk(); 43
Når programmet kompileres class Bygig { Bygig() { super(); System.out.pritl("Bygig"); // class Bygig class Bolighus exteds Bygig { Bolighus() { super(); System.out.pritl("Bolighus"); // class Bolighus Java føyer selv på super() i disse tre kostruktøree før programmet utføres class Blokk exteds Bolighus { Blokk() { super(); System.out.pritl("Blokk"); public static void mai(strig[] args) { ew Blokk(); // class Blokk 44
Når programmet utføres 4. class Bygig { Bygig() { super(); System.out.pritl("Bygig"); // class Bygig class Bolighus exteds Bygig { Bolighus() { super(); System.out.pritl("Bolighus"); // class Bolighus 5. Til Object si kostruktør 3. 2. class Blokk exteds Bolighus { Blokk() { super(); System.out.pritl("Blokk"); public static void mai(strig[] args) { ew Blokk(); // class Blokk Her starter eksekverige 1. 45
Når programmet utføres (forts.) 7. Nå er Bygig skrevet ut 8. Nå er Bolighus skrevet ut 9. Nå er Blokk skrevet ut class Bygig { Bygig() { super(); System.out.pritl("Bygig"); // class Bygig class Bolighus exteds Bygig { Bolighus() { super(); System.out.pritl("Bolighus"); // class Bolighus class Blokk exteds Bolighus { Blokk() { super(); System.out.pritl("Blokk"); public static void mai(strig[] args) { ew Blokk(); // class Blokk 6. Tilbake fra Object si kostruktør 46
Eksempel 4 class Bygig { Bygig() { System.out.pritl("Bygig"); Hva skjer i dette eksempelet? class Bolighus exteds Bygig { Bolighus(it i) { System.out.pritl("Bolighus r " + i); class Blokk exteds Bolighus { Blokk() { System.out.pritl("Blokk"); Merk: Kostruktøre i klasse Bolighus har å e parameter. public static void mai(strig[] args) { ew Blokk(); 47
Når programmet kompileres class Bygig { Bygig() { super(); System.out.pritl("Bygig"); // class Bygig Java legger igje til kall på super() i alle kostruktøree. class Bolighus exteds Bygig { Bolighus(it i) { super(); System.out.pritl("Bolighus"); // class Bolighus class Blokk exteds Bolighus { Blokk() { super(); System.out.pritl("Blokk"); public static void mai(strig[] args) { ew Blokk(); // class Blokk Me: Kallet matcher ikke metode i atall parametre! Mulige løsiger: 1. Selv legge til kall på super, med argumet, i kotruktøre Blokk. 2. Legge til e tom kostruktør i Bolighus. 48