Abstrakte metoder og klasser Uke 9 INF1010, 27. februar 2007, Abstrakte klasser og grensesnitt (interface) Stein Gjessing Inst for Informatikk Univ. i Oslo n Abstrakte metoder n abstract før deklarasjonen av en metode betyr at metoden ikke inneholder noe program / kode ( ; istedenfor {... (eksempel neste side) ) n Subklasser må da gi kode til denne metoden. n Abstrakte klasser n klasse med abstract før class n kan (men må ikke) inneholde abstrakte metoder n En klasse med en abstrakt metode må deklareres som en abstrakt klasse. n Kan ikke lage objekter av abstrakte klasser (må vente til vi har en ikke-abstrakt subklasse) 2 abstract class Ansatt { String navn; double timelonn; Abstrakte metoder og klasser abstract double beregnbonus(); class Deltidsansatt extends Ansatt { double beregnbonus() { return 0; Ikke lov å si new Ansatt()! navn timelonn beregnbonus(); Subklassene arver på vanlig måte alle egenskapene fra den abstrakte superklassen navn timelonn Heltidsansatt objekt navn timelonn Pekere av abstrakte typer (selv om det ikke finnes slike objekter) Ansatt enperson Deltidsansatt objekt Deltidsansatt Heltidsansatt Ansatt enannenperson navn timelonn Heltidsansatt objekt class Heltidsansatt extends Ansatt { int ansiennitetsfaktor; double beregnbonus() { return timelonn* ansiennitetsfaktor; beregnbonus(); ansiennitetsfaktor beregnbonus(); beregnbonus() beregnbonus(); ansiennitetsfaktor beregnbonus() return 0; beregnbonus() return timelonn* ansiennitetsfaktor Ellers helt som vanlige subklasser med polymorfi (virtuell metoder) 3 4
Når bruker vi abstrakte metoder og klasser? n Abstrakte metoder n Vi lager en klasse som vi vet må inneholde en bestemt metode, men vi vet også at innholdet vil variere i alle subklassene n Må lag en subklasse som tvinges til å gi koden n Abstrakte klasser n Vi har to eller flere klasse B, C,...D som har felles deler n Vi lager da en klasse A som inneholder disse felles delene, og de andre klassene B,C,..,D gjøres til subklasser av A n Eks: Heltidsansatte og Deltidsansatte i et varehus. Lager da den abstrakte felles-klassen Ansatt, og det som blir igjen i Heltidsansatt og Deltidsansatt, blir da bare de spesielle tillegget disse har. n Vi deklarerer en klasse abstrakt når vi ønsker at ingen skal lage objekter av klassen (Abstrakt klasse der ingen metoder er abstrakte) n Vi lager en klasse abstrakt når den inneholder abstrakte metoder, dvs. metoder det ikke er meningsfylt å gi innhold til UML klassehierarki med abstrakt klasse Ansatt abstract 5 6 Arv n I Java kan en klasse bare arve egenskapene til én annen klasse (en superklasse). n Hva skal vi gjøre hvis vi ønsker at et objekt skal inneholde mange forskjellige egenskaper fra forskjellige superklasser? n På de neste sidene: n Begrepshierarkiet i et biliotek Motivasjon for nytt begrep (interface): Analyse av bibliotek n Bøker, tidsskrifter, er, videoer, mikrofilmet materiale, antikvariske bøker, flerbindsverk, oppslagsverk, upubliserte skrifter, n En del felles egenskaper n antall eksemplarer, hylleplass, identifikasjonskode () n for det som kan lånes ut: Er utlånt?, navn på låner,... (TilUtlån) n for det som er antikvarisk: Verdi, forskringssum,... (Antikvarisk) n Spesielle egenskaper: n Bøker: Forfatter, tittel, forlag n Tidsskrifter: Årgang, nummer, utgiver n : Tittel, artist, komponist, musikkforlag På de neste sidene betyr En klasse i et subklassehierarki 7 (og ikke en klassedatastruktur) 8
Tvilsomt begrepshierarki Forslag til subklassehierarki Utlånbart Omrokkering uten suksess IkkeLånbart Tidskrift U U TidsskriftUtl Utlånbar IkkeLånbar Utlånbar IkkeLånbar UtlånbartTid sskriftnr IkkeLånbartTi dsskriftnr Tidsskriftnr 9 10 Samle lik oppførsel: interface Hva er et grensesnitt (interface)? interface TilUtlån n En samling egenskaper (en rolle) som ikke naturlig hører hjemme i et arve-hierarki Tidskriftnr n En samling egenskaper som mange forskjellige ting av forskjellige typer kan anta n For eksempel Utlånbar Utlånbar Utlånbart Tidsskriftnr n Kan delta i konkurranse (startnummer, resultat,.. Mennesker, biler, hester kan delta i konk.) n Svømmedyktig (mennesker, fugler er svømmed.) n Her: Antikvarisk (møbler, bøker,. ) Kan lånes ut (biler, bøker, festklær, ) n En klasse kan også tilføres et interface (i tillegg til arveegenskapene i klassehierarkiet) n Dvs. en klasse kan spille to roller 11 12
Hva er et grensesnitt (interface)? n Et interface likner en abstrakt klasse n Alle metodene i en interface er abstrakte n En interface inneholder ingen variable eller annen datastruktur (men kan ha konstanter) n En klasse som arver egenskapene til et interface må selv putte inn kode i alle de abstrakte metodene (og deklarere passende variable som disse metodene bruker). n En klasse kan arve egenskapene til mange grensesnitt (men bare en klasse) n Å arve (metoder) = å spille en rolle 13 interface TilUtlån Utlånbar Flere grensesnitt Verk Video AntekvUtlånbr Antikvarisk IkkeLånbar Utlånbart Tidsskriftnr Utlånbart, Antekvarisk Tidsskrift Tidskriftnr n En klasse kan tilføres et ubegrenset antall interface-er n Dvs. en klasse kan spille et ubegrenset antall roller interface Antikvarisk IkkeLånbartTids skriftnr Antikvarisk tidsskriftnr 14 Nytt eksempel Hvis vi ønsker at noen objekter også skal kunne spille rollene (ha egenskapene) Skatt og Miljø : Enkelt eksempel med bil-hierarkiet class Bil { String regnr; class Lastebil extends Bil { double lastevekt; Bil Skatt interface Skatt { double toll( ) ; int momssats() ; toll ( ); momssats( ); interface Skatt { double toll( ) ; int momssats() ; Skatt Lastebil interface Miljo { int co2utslipp ( ); boolean svanemerket ( ) ; Miljo co2utslipp( ); svanemerket( ); 15 interface Miljo { int co2utslipp ( ); boolean svanemerket ( ) ; Miljo 16
Tre nye klasser som kan spille mange roller Nytt Java-ord: implements (1) Skatt Bil Miljo rollen (i arv) fra klassehierarkiet Lastebil Personbil class Personbil extends Bil implements Skatt { int antpass; double momsgrunnlag = 150000; public double toll( ) { return momsgrunnlag * 0.5; public int momssats( ) {return 25; rollen Skatt LastebilMedSkattogMiljo MiljoBil Men metodene må (dessverre) skrives på nytt hver gang de brukes 17 class Bil { String regnr; interface Skatt { double toll( ) ; int momssats() ; Skatt Bil Personbil 18 Nytt Java-ord: implements (2) class MiljoBil extends Personbil implements Miljo { int utslipp = 200; public int co2utslipp ( ) {return utslipp; public boolean svanemerket () { return false; class LastebilMedSkattogMiljo extends Lastebil implements Skatt, Miljo { double innkjopspris = 200000; int utslipp = 400; public double toll( ) { return innkjopspris * 0.1; rollen Skatt public int momssats( ) {return 20; public int co2utslipp ( ) {return utslipp; rollen Miljo public boolean svanemerket () { return false; MiljoBil arver rollen Skatt fra Personbil Rollene i (arv fra) klassehierarkiet rollen Miljo Den rød-grønne regjeringen vil sikkert gjøre noe med det 19 Bil minbil; Lastebil minlast; Et objekt og noen pekere LastebilMedSkattogMiljø denne; Skatt skatteobjekt; Miljo miljoting; Hva kan vi se gjennom de forskjellige pekerene? Det er sant: Vi kan ha pekere av interface-type new LastebilMedSkattogMiljø() regnr lastevekt toll ( ); momssats( ); co2utslipp( ); svanemerket( ); utslipp innkjopspris Object obj; Bil Lastebil rollen Skatt rollen Miljo egne ting (og egen rolle) 20
Legg til metoder for å skrive ut på skjerm: Skriv i LastebilMedSkattOgMiljo class Bil { String regnr; void skriv(){ System.out.println( Registreringsnummer: " + regnr); class Lastebil extends Bil { double lastevekt; void skriv (){ super.skriv(); System.out.println("Lastevekt: " + lastevekt); 21 class LastebilMedSkattOgMiljo extends Lastebil implements Skatt, Miljo { double innkjopspris = 200000; int utslipp = 400; public double toll( ) { return innkjopspris * 0.1; public int momssats( ) {return 20; public void skrivskatt( ) { System.out.println("Innkjøpspris " + innkjopspris); public int co2utslipp ( ) {return utslipp; public boolean svanemerket () { return false; public void skrivmiljo( ) { System.out.println("Utslipp " + utslipp); public void skriv( ) { System.out.println( Lastebil med skatt og miljø: "); super.skriv( ); skrivskatt(); skrivmiljo(); (Skatt og Miljo som før) Det er ikke naturlig at Skatt og Miljo skal kreve en skriv -metode (Som før) 22 Skriv i LastebilMedSkattogMiljo Bil minbil; Lastebil minlast; LastebilMedSkattogMiljø denne; Skatt skatteobjekt; Miljø miljøting; LastebilMedSkattogMiljø-objekt regnr skriv() lastevekt skriv() toll ( ); momssats( ); co2utslipp( ); Object obj; Tilbake til biblioteket Klassehierarki, forenklet bibliotek interface TilUtlån svanemerket( ); TilUtlaan IkkeUtlaan TilUtlaan IkkeUtlaan public void skriv( ) { System.out.println ( Lastebil med skatt og miljø: "); super.skriv( ); skrivskatt(); skrivmiljo(); utslipp innkjopspris skrivmiljo() skrivskatt() skriv() (egne ting og) egen rolle 23 24
Forenklet bibliotek TilUtlaan interface TilUtlån TilUtlaan IkkeUtlaan Ordet abstract kan sløyfes før metodenavnet i et interface (det er jo helt opplagt) abstract class { String tittel; abstract class extends { String forlag; int trykningsår; interface TilUtlaan { abstract void låne(string låner) ; abstract void levere() ; abstract boolean utlånt() ; static final String ingen = "ingen"; // Slutt interface TilUtlaan 25 interface TilUtlaan TilUtlaan IkkeUtlaan Bare disse to klassene kan vi lage objekter av TilUtlaan har både egenskapene til og egenskapene til TilUtlaan. Objekter av denne klassen kan spille begge rollene! class TilUtlaan extends implements TilUtlaan { String låner = ingen; public void låne (String l) { låner = l; public void levere() { låner = ingen; public boolean utlånt() { return låner!= ingen; // Slutt class TilUtlaan class IkkeUtlaan extends { 26 Se på implementasjonen igjen: interface TilUtlaan { abstract void låne(string låner) ; abstract void levere() ; abstract boolean utlånt() ; static final String ingen = ingen"; class TilUtlaan extends implements TilUtlaan { String låner = ingen; public void låne (String l) { låner = l; public void levere() { låner = ingen; public boolean utlånt() { return låner!= ingen; Metodene i et interface er veldig virtuelle Dette er de tre metodene som vi må love å implementere 27 interface TilUtlaan { abstract void låne(string låner) ; abstract void levere() ; abstract boolean utlånt() ; static final String ingen = ingen"; abstract class extends { String komponist, artist, musikkforlag; class TilUtlaan extends implements TilUtlaan { String låner = ingen; public void låne(string l) { låner = l; public void levere() { låner = ingen; public boolean utlånt() { return låner!= ingen; // Slutt class TilUtlaan interface TilUtlån class IkkeUtlaan extends { TilUtlaan IkkeUtlaan Her er de tre metodene igjen 28
Mer om grensesnitt (interface) n Navnet på et Interface (grensesnitt) kan brukes som klassenavn når vi lager pekere (så vi på side 20) n Vitsen med et grensesnitt er å spesifisere hva som skal gjøres (ikke hvordan) n Det kan godt være flere implementasjoner av et grensesnitt (flere klasser kan implementere det). n Vi vet: En klasse kan implementerer (flere) grensesnitt samtidig som klassen også er subklasse av (bare) en annen klasse. n En implementasjon (av et grensesnitt) skal kunne endres uten at resten av programmet behøver å endres. 29 Anta at vi skal lage et register i et bibliotek 4 BI JavaGently Addison-Wesley 1998 CU Favoritter Grieg Kyrkjebø Musikkforlaget ingen BU JustJava Sun 1998 Kari CI Favourites Wonder,Stevie Dion,Celine BMG Filformat: Først antall poster på filen For hver post: - dokumenttypen (BU, BI, CU eller CI) - tittel - Hvis : forlag år - Hvis TilUtlån: Også låner - Hvis : komponist / artist / musikkforlag - Hvis TilUtlån: Også låner 30 register Innlesning Register - objekt register Utskrift Register - objekt innfil antdok alleer utfil alleer void lesfrafil() d = null; String dokumenttype; In innfil = new In( dokumentfil.txt ); antdok = innfil.inint( ); for (int i=1; i<=antdok; i++) { dokumenttype = innfil.inword( ); if (dokumenttype.equals("bu")) d = new TilUtlaan(); else if (dokumenttype.equals("bi")) d = new IkkeUtlaan(); else if (dokumenttype.equals("cu")) d = new TilUtlaan(); else if (dokumenttype.equals("ci")) d = new IkkeUtlaan(); d.lesfra(innfil); alleer.put(d.tittel,d); // Slutt for TilUtlaan TilUtlaan TilUtlaan TilUtlaan 31 void skrivtilfil() d = null; String dokumenttype; Out utfil = new Out( dokumentfil.txt ); utfil.outln(alledokumenter.size( )); for ( d: alleer.values()) { d.skrivtilfil(fil); d TilUtlaan TilUtlaan TilUtlaan TilUtlaan alleer.values() 32
Metoden låne i Register Klasse- og interface-tilhørighet (igjen) void låne() void låne() throws IOException { boolean utlånt() d = null; String h; void levere() System.out.print( Tittel: "); h = in.readstring( ); d = alleer.get(h); if (d==null) System.out.println("Beklager, denne har vi ikke"); else if (d instanceof TilUtlaan) { TilUtlaan t = (TilUtlaan) d; if (t.utlånt()) { System.out.println("Beklager, utlånt"); else { System.out.print( Låners navn: "); String n = in.readstring( ); t.låne(n); // slutt kan lånes ut // Slutt if (d instanceof TilUtlaan) else System.out.println("Beklager, denne låner vi ikke ut"); // Slutt låne t 33 n Test med operatoren instanceof if (d instanceof TilUtlaan) p instanceof C n Gir TRUE dersom p peker på et objekt av klassen C eller en subklasse av C, eller dersom p peker på en klasse som implementerer interfacet C n Endring med casting d d = alleer.get(h); TilUtlaan t = (TilUtlaan) d; t ser bare TilUtlån-egenskapene! n OK, dersom d spiller rollen TilUtlaan, dvs. er et objekt av en av klassene TilUtlaan eller TilUtlaan Object TilUtlaan TilUtlaan 34 leveretilbake i Register Indre klasser void leveretilbake() { d = null; String h; System.out.print( Tittel: "); h = in.readstring( ); d = alleer.get(h); if (d==null) System.out.println("Beklager, feil tittel"); else if (d instanceof TilUtlaan) { TilUtlaan t = (TilUtlaan) d; if (t.utlånt()) { t.levere(); System.out.println("Takk"); else System.out.println("Beklager, denne er ikke utlånt"); // Slutt if (d instanceof TilUtlaan) void låne() boolean utlånt() void levere() t 35 n Klasser i Java kan defineres inni hverandre. n Objekter i den indre klassen kan referere til metoder og variable i sitt omsluttende objekt! n + Lettvint + Skjuler implementasjon n Flere feilmuligheter Du må altså opprette et objekt av den ytre klassen før du får lov til å lage objekter av den indre klassen class Register { HashMap<String,Person> liste; class Person { String navn; void registrer() {... liste.put(navn,this);... // Slutt class Person // Slutt class Register Ikke viktig i inf1010 36
Et utvalg fra Javas klassehierarki class HashMap<K,V> class Object { // Alle objekters mor boolean equals(object obj)... Object clone()... public final class String extends Object { public final class Math extends Object { public class Date extends Object { public abstract class Calendar extends Object { public interface Map<K,V> { public interface Collection<E> { public interface Iterator<E> { public abstract class AbstractMap<K,V> extends Object implements Map<K,V> { Alle klasser er subklasser av class Object. Hvis klassedeklarasjonen ikke har med extends, tolker kompilatoren det som extends Object class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { // Hemmelig datastruktur public void put(k key, V value) { public V remove(object key) { public V get(object key) { public boolean containskey(object key) { public boolean containsvalue(object value) { Java har etter hvert mange klasser som kan brukes til å ta vare på objekter: Vector, ArrayList, Collection, HashMap HashSet, LinkedList, Stack, TreeSet, TreeMap, ) public int size( ) { public class HashMap <K,V> extends AbstractMap <K,V> implements Map <K,V>, Cloneable, Serializable { V get(object key) { public Collection<V> values( ) { void put (K key, V value) { K: Key, E: Element, V: Value 37 38 // slutt class HashMap class HashMap class HashMap extends AbstractMap implements Map, Cloneable, Serializable { // Hemmelig datastruktur public void put(object key, Object value) { public Object remove(object key) { public Object get(object key) { public boolean containskey(object key) { public boolean containsvalue(object value) { public int size( ) { public Collection values( ) { Uten typer, bare med Object, blir det slik public interface Collection{ public int size(); class HashMap<K,V> { <Hemmelig datastruktur> class Ukjent<V> implements Collection<V> { public void put(k nokkel, V verdi ){ public Collection<V> values( ) { Ukjent<V> u = new Ukjent<V> ( ) ; return u;... HashMap og Collection HashMap har altså sine egne implementasjoner av Collection som er hemmelig for oss utenfor, men siden alle metodene er kjent kan vi kalle på disse (på neste side) // slutt class HashMap 39 40
Implementasjon av Collection Grensesnitt (interface) enda en gang void visalleer() alleer For ( d: alleer.values()) { d.vispaaskjerm(); // slutt for Collection Class Ukjent Ukjent-objekt d Collection values() n Et grensesnitt (interface) har bare n konstanter (static final - eks static final int ANTALL = 4;) n metodenavn med parametre, men ikke kode (husk ;) n Bruker interface i steden for class før navnet n Gir en type / rolle som andre må implementere n class ABC implements ButikkSystem {...her gis kode for alle metodene i ButikkSystem... n Meget nyttig, brukes mye ved distribuerte systemer og generelle programbiblioteker som Javas eget n Ulempe: Koden/implementasjonen må gjøres mange ganger n Mer generelt kjent under navnet ADT =Abstrakt DataType, Vi definerer hva en ny datatype skal gjøre, ikke hvordan dette gjøres. n Det kan være mange mulige implementasjoner (=måter å skrive kode på) som lager en slik datatype. n Hva som er beste implementasjon må avgjøres etter hvilken bruk vi har. -objekt 41 42