INF1010 våren 2010 Torsdag 4. februar Arv og subklasser del I Stein Gjessing Institutt for informatikk 1
Emneoversikt subklasser (2 uker) 2
Hva er en subklasse? En klasse, K, beskriver objekter med visse felles egenskaper En subklasse av K, S, beskriver objekter som har de samme egenskapene (som beskrevet av K), men i tillegg er objektene noe mer, de har flere egenskaper... class K {... class S extends K {... Nytt Java nøkkelord: extends Navn på klasser og subklasser (K og S her) bør best mulig beskrive hva klassene representerer 3
Eksempel: Universitetsregister I et mini-system for Universitetet i Oslo skal alle studenter registreres med navn og telefonnummer (åtte siffer), samt hvilket studieprogram de er tatt opp til. Det skal være mulig for studenter å bytte program. Systemet skal også inneholde informasjon om de ansatte ved universitetet, nemlig navn, telefonnummer, lønnstrinn og antall arbeidstimer per uke. Tekniskadministrativt ansatte har en arbeidsuke på 37,5 timer, mens vitenskapelig ansatte har 40-timers arbeidsuke. Alle personer skal behandles som......... 4
Eksempel: Universitetsregister I et mini-system for Universitetet i Oslo skal alle studenter registreres med navn og telefonnummer (åtte siffer), samt hvilket studieprogram de er tatt opp til. Det skal være mulig for studenter å bytte program. Systemet skal også inneholde informasjon om de ansatte ved universitetet, nemlig navn, telefonnummer, lønnstrinn og antall arbeidstimer per uke. Tekniskadministrativt ansatte har en arbeidsuke på 37,5 timer, mens vitenskapelig ansatte har 40-timers arbeidsuke. Alle personer skal behandles som......... Substantivmetoden 5
Klassen Student class Student { String navn; int tlfnr; String program; void skrivdata() { System.out.println("Navn: " + navn); System.out.println("Telefon: " + tlfnr); System.out.println("Studieprogram: " + program); boolean gyldigtlfnr() { return tlfnr >= 10000000 && tlfnr <= 99999999; void byttprogram(string nytt) { program = nytt; 6
Klassen Ansatt class Ansatt { String navn; int tlfnr; int lønnstrinn; int antalltimer; void skrivdata() { System.out.println("Navn: " + navn); System.out.println("Telefon: " + tlfnr); System.out.println("Lønnstrinn: " + lønnstrinn); System.out.println("Timer: " + antalltimer); boolean gyldigtlfnr() { return tlfnr >= 10000000 && tlfnr <= 99999999; void lønnstillegg(int tillegg) { lønnstrinn += tillegg; 7
Student vs Ansatt Felles variable: navn, tlfnr Egne variable: Student: program Ansatt: lønnstrinn, antalltimer Felles metoder: gyldigtlfnr() Lignende metoder: skrivdata() Egne metoder: Student: nyttprogram(string nytt) Ansatt: lønnstillegg(int tillegg) 8
Klassen Person Kan samle det som er felles i en egen, mer generell, klasse: class Person { String navn; int tlfnr; boolean gyldigtlfnr() { return tlfnr >= 10000000 && tlfnr <= 99999999; Klassen Person beskriver alt som er felles for studenter og ansatte 9 9
Student og Ansatt som subklasser Kan nå gjøre Student og Ansatt til subklasser av Person: class Student extends Person { String program; void byttprogram(string nytt) { program = nytt; class Ansatt extends Person { int lønnstrinn; int antalltimer; Angir at klassene Student og Ansatt er subklasser (= utvidelser) av klassen Person. void lønnstillegg(int tillegg) { lønnstrinn += tillegg; Hva med skrivdata()? - Kommer tilbake til denne Nytt Java nøkkelord: extends 10
class Student { String navn; int tlfnr; String program; class Person { String navn; int tlfnr; boolean gyldigtlfnr() {... boolean gyldigtlfnr() {... void byttprogram(string nytt) {... class Student extends Person { String program; void byttprogram(string nytt) {... Eksempler på objekter av klassene navn tlfnr gyldigtlfnr() navn tlfnr program gyldigtlfnr() byttprogram() navn tlfnr gyldigtlfnr() program byttprogram() 11
Bruk av en subklasse Vi kan bruke variable og metoder i en subklasse på samme måte som om vi hadde definert alt i én klasse: Uten bruk av subklasser (før): eller Med bruk av subklasser (nå): class Student { String navn; int tlfnr; String program; boolean gyldigtlfnr() {... void byttprogram(string nytt) {... Navn: stud class Person { String navn; int tlfnr; boolean gyldigtlfnr() {... class Student extends Person { String program; void byttprogram(string nytt) {... Navn: stud navn tlfnr program gyldigtlfnr() byttprogram() Type: Student Type: Student Student stud = new Student(); stud.gyldigtlfnr(); String prog = stud.program; navn tlfnr gyldigtlfnr() program byttprogram() 12
Time out Det er to forskjellige innebygde typer i Java: Primitive typer boolean, byte, short, int, long, char, float, double Referanse-typer Beskriver pekere til klasse-objekter * (fordi klasse-objekter ikke har navn) Jeg sier referanse og peker om hverandre Konstanter og variable av disse typene er de basale byggestene i Java, og er det alle objekter er bygget opp av (i tillegg er det metoder i objekter) * i tillegg finnes det referanser/pekere til arrayer 13
UML-notasjon for subklassehierarki class Person { String navn; int tlfnr; boolean gyldigtlfnr() {... class Student extends Person { String program; void byttprogram(string nytt) {... class Ansatt extends Person { int lønnstrinn; void lønnstillegg (int tillegg){ lønnstrinn += tillegg; Person Student Ansatt 14 14
Igjen: Hva er en subklasse? En subklasse er en klasse som bygger på en allerede spesifisert klasse, og som dermed arver dennes egenskaper i tillegg til å utvide med egne egenskaper (metoder/variable/konstanter). En subklasse er altså en mer spesialisert utgave av klassen den bygger på. Klassen vi bygger på kalles en superklasse. 15
Generalisering spesialisering Mengden av alle Personer navn tlfnr Person Student Mengden av alle Studenter navn tlfnr lønnstrinn antalltimer Ansatt Mengden av alle Ansatte navn tlfnr program Sub-klasse ~ Sub-mengde (del-mengde) 16
Klasse-hierarkier Det er mulig å definere subklasser av en subklasse: class Person { String navn; int tlfnr; boolean gyldigtlfnr() {... class Student extends Person { String program; void byttprogram(string nytt){... class MasterStudent extends Student { String veileder; Obs: Her er MasterStudent en subklasse av både Student og Person, og arver egenskaper fra begge disse. navn tlfnr gyldigtlfnr() program byttprogram() veileder MasterStudent-objekt 17
Generalisering spesialisering Mengden av alle Personer navn tlfnr gyldigtlfnr() Person Student Mengden av alle Studenter navn tlfnr gyldigtlfnr() program byttprogram() MasterStudent Mengden av alle MasterStudenter navn tlfnr gyldigtlfnr() program byttprogram() veileder 18
Klasser - Subklasser Klassehierarki: Bil class Bil {... Lastebil Personbil Drosje class Personbil extends Bil {... class Lastebil extends Bil {... class Drosje extends Personbil {... 19
Klasse- hierarki: Personbil Bil Klasser - Subklasser class Bil { <lys beige egenskaper> class Personbil extends Bil { <røde egenskaper> class Lastebil extends Bil { <grønne egenskaper> class Drosje extends Personbil { <gule egenskaper> Alle lastebiler Lastebil Drosje Alle biler Alle drosjer Alle personbiler 20
Hvorfor bruker vi subklasser? Klasser og subklasser avspeiler virkeligheten Bra når vi skal modellere virkeligheten i et datasystem Klasser og subklasser avspeiler arkitekturen til datasystemet / dataprogrammet Bra når vi skal lage et oversiktlig stort program Klasser og subklasser kan brukes til å forenkle og gjøre programmer mer forstålig, og spare arbeid: Gjenbruk av programdeler Bottom up programmering Lage verktøy Top down programmering Postulere verktøy 21
Gjenbruk av deler av programmer Viktig å ikke måtte skrive ny kode hver gang man skal programmere noe nytt Gjenbruk mest mulig av kode du har skrevet før Lag kode med henblikk på et den skal brukes (til noe liknende) senere Lag biblioteker Bruk andres bibliotek Javas eget bibliotek Strukturering av kode ( gjenbruk i samme program) Inf1000: Gjenbruk av metoder og klasser 22
Gjenbruk ved hjelp av klasser / subklasser Ved sammensetning (komposisjon) (i inf1000): Deklarer pekere til objekter av klasser du har skrevet før Lag objekter av disse klassen Kall på metoder i disse klassene Ved arv (nytt i inf1010): Lag en ny klasse som utvider den eksisterende klassen (spesielt viktig ved litt større klasser) Føy til ekstra variable og metoder 23
Gjenbruk ved sammensetning har dere allerede sett mange eksempler på i INF1000. Eksempel: Gjenbruk ved sammensetning / komposisjon class PersonRegister { HashMap venner = new HashMap(); Noe p = new Noe(); String navn = Ole-Morten"; venner, p og navn er /* Diverse metoder */ deklarert som pekere til objekter av andre klasser som allerede eksisterer. venner p navn Ole-Morten 24
Gjenbruk ved arv Objekter av klassene class Bok { String tittel, forfatter; class Fagbok extends Bok { double dewey; class Skjønnlitterærbok extends Bok { String sjanger; class Bibliotek { Bok b1 = new Fagbok(); Bok b2 = new Skjønnlitterærbok(); Arv Komposisjon Gjenbrukes Gjenbrukes 25
Når skal vi bruke arv? Generelt: Ved er-en relasjon mellom objektene. En Student er en Person En Ansatt er en Person Hva med relasjonene roman bok? En roman er en bok (arv). kapittel bok? Et kapittel er ikke en bok, men et kapittel er en del av en bok, og en bok har/består av kapitler (sammensetn.) Relasjoner som har-en og består-av skal ikke modelleres som subklasser, men ved hjelp av sammensetning (som datafelt (konstanter/variable)). 26
Oppgave Hvor er det naturlig å bruke komposisjon og hvor er det naturlig med arv i disse tilfellene? Relasjon mellom Komposisjon Arv vare - varelager nyhetskanal - kanal person - personregister cd - spor (sanger) PC - datamaskin gaupe - rovdyr fly - transportmiddel motor - bil 27
Ulike referansetyper Person pers; Student stud; class Person { String navn; int tlfnr; boolean gyldigtlfnr() {... pers stud gyldigtlfnr() navn tlfnr class Student extends Person { String program; void byttprogram(string nytt){... byttprogram() program Objekt av klassen Student Vi kan ha pekere både av typen Student og av typen Person 28
Ulike måter å se et objekt på Navn: stud Type: Student navn tlfnr gyldigtlfnr() program byttprogram() Navn: pers Typen (klassen) til hele dette objektet er Student Type: Person Student stud; Person pers; stud = new Student(); pers = stud; Typen (klassen) til et objekt er uforanderlig. Et objekt kan likevel fremtre for oss på ulike måter. Et objekt av klassen class Student extends Person {... kan vi se på som et objekt av typen (klassen) Person: da er egenskapene som er spesielle for Student ikke synlige (men de er der fortsatt!). Student: da er både Person- og Studentegenskapene synlige for oss. Det er referansens type som avgjør hvordan objektet fremtrer. (med untak av virtuelle metoder, som vi snart skal lære hva er) (Det er lov å skrive: pers = new Student(); 29
Eksempler Student s class Person { String navn; int tlfnr; boolean gyldigtlfnr() {... class Student extends Person { String program; void byttprogram(string nytt) {... String navn; int tlfnr; gyldigtlfnr() String program; byttprogram() Person p String navn; int tlfnr; gyldigtlfnr() String program; byttprogram() Anta: Student s = new Student(); Person p = new Student(); Hvilke av følgende uttrykk er nå lovlige? s.navn = Ole-Morten"; s.gyldigtlfnr(); s.program = "Matte"; s.byttprogram("data"); p.navn = Ole-Ivar"; p.gyldigtlfnr(); p.program = "Matte"; p.byttprogram("data"); 30
IO feil En metode som kan komme til å gjøre en IO-feil må enten behandle denne selv, eller kaste feilen videre (også i main): public void mittprogmedio( ) throws IOException { < kode som gjør fil-behandling> I Java-biblioteket: class IOException extends Exception {... Vi skal lære mye mer om unntak og feilbehandling senere throws er et Java nøkkelord 31
Inn fra tastatur i Java main les Hilsen klassedatastruktur import java.io.*; import java.util.*; class Hilsen { public static void main (String [] args) throws IOException { Scanner les= new Scanner (System.in); System.out.println( Hva heter du?"); String navn = les.nextline ( ); System.out.println( God dag " + navn ); snidil:>javac Hilsen.java snidil:>java Hilsen Hva heter du? Stein Gjessing God dag Stein Gjessing snidil:> Kaster IOunntak til runtimesystemet navn 11 konstruktører 47 metoder pluss plass til å lagre en streng (en tekst) Stein Gjessing String nextline() Objekt av klassen Scanner Et objekt av klassen String 32
Om å lese tall (Utdrag av et program) main tastaturparser import java.io.*; import java.util.*; Scanner tastaturparser= new Scanner (System.in); double tall; int antall; double nextdouble() int nextint() System.out.println( Tast inne et kommatall: ); tall = tastaturparser.nextdouble(); System.out.println( Tast inne et tall: ); Objekt av klassen Scanner som henter data fra System.in (tastaur) antall = tastaturparser.nextint(); System.out.println ( Du skrev + tall + og + antall );
import java.io.*; import java.util.*; Innlesing fra fil Java original main filleterinn boolean hasnext() class LesFraFil { Objekt av klassen Scanner int nextint() public static void main (String [ ] args) throws IOException { Scanner filleterinn = new Scanner (new File ("minfil.txt )); int tall; while(filleterinn.hasnext()) { tall = filleterinn.nextint(); System.out.println(tall); // slutt main // slutt class LesFraFil DETTE GÅR BRA HVIS FILEN BARE INNE- HOLDER HELTALL!! 34
Utskrift til fil - Java original main filut PrintWriter filut = new PrintWriter (new FileWriter ( minutfil.txt )); // Utskrift skjer som til skjerm: filut.println( utskrift + 17 ): For at innholdet på den nye filen skal bevares må vi til slutt si: Dette objektet skriver på filen minutfil.txt void println() minutfil.txt filut.close( ); 35
Omdefinering av metoder - polymorfi Vi har sett at det med subklasser er mulig å utvide en eksisterende klasse med nye metoder. En subklasse kan også definere en metode med samme signatur som en metode i superklassen, men med ulikt innhold. Den nye metoden vil omdefinere (erstatte) metoden som er definert i superklassen. Metoder som kan omdefineres på denne måten kalles virtuelle metoder. I Java er alle metoder virtuelle, så sant de ikke er deklarert med final. Virtuelle metoder = polymorfi 36
Polymorfi: eksempel class Hund { //... void bjeff() { System.out.println("Voff-voff"); class Rasehund extends Hund { //... void bjeff() { System.out.println("Vov-vov"); For objekter av typen Hund er det denne metoden som gjelder. For objekter av typen Rasehund er det denne metoden som gjelder. Anta: Hund h = new Hund(); Rasehund r = new Rasehund(); Hund g = r; Hva skrives ut ved hvert av kallene: h.bjeff(); r.bjeff(); g.bjeff(); 37
Polymorfi: eksempel Hund h Rasehund r Hund g void bjeff() { System.out.println("Voff-voff"); void bjeff() { System.out.println("Voff-voff"); void bjeff() { System.out.println("Vov-vov"); Anta: Hva skrives ut ved hvert av kallene: Hund h = new Hund(); Rasehund r = new Rasehund(); Hund g = r; h.bjeff(); r.bjeff(); g.bjeff(); voff-voff vov-vov vov-vov 38
Polymorfi: skrivdata I universitets-eksemplet så vi at klassene Student og Ansatt hadde nesten like skrivdata-metoder: // I klassen Student: void skrivdata() { System.out.println("Navn: " + navn); System.out.println("Telefon: " + tlfnr); System.out.println("Studieprogram: " + program); // I klassen Ansatt: void skrivdata() { System.out.println("Navn: " + navn); System.out.println("Telefon: " + tlfnr); System.out.println("Lønnstrinn: " + lønnstrinn); System.out.println("Timer: " + antalltimer); 39
Nøkkelordet super Nøkkelordet super brukes til å aksessere variable / metoder i objektets superklasse. Dette kan vi bruke til å la superklassen Person ha en generell skrivdata, som så kalles i subklassene: // I klassen Person: void skrivdata() { System.out.println("Navn: " + navn); System.out.println("Telefon: " + tlfnr); // I klassen Student: void skrivdata() { super.skrivdata(); System.out.println("Studieprogram: " + program); // Tilsvarende i klassen Ansatt: void skrivdata() { super.skrivdata(); System.out.println("Lønnstrinn: " + lønnstrinn); System.out.println("Timer: " + antalltimer); 40
class StudentRegister { public static void main(string [] args) { Student stud = new Student(); Person pers = new Person(); stud.skrivdata(); pers.skrivdata(); // Her brukes definisjonen i Student // Her brukes definisjonen i Person Person pers2 = stud; pers2.skrivdata(); // Hvilken definisjon benyttes her? Person pers Student stud Person pers2 void skrivdata() { System.out.println("Navn: " + navn); System.out.println("Telefon: " + tlfnr); void skrivdata() { System.out.println("Navn: " + navn); System.out.println("Telefon: " + tlfnr); Regel: Det er objekttypen, ikke pekertypen, som avgjør hvilken definisjon som gjelder når en metode er virtuell. void skrivdata() { super.skrivdata(); System.out.println("Studprgm: " + prgm); 41
Omdefinering av variable En subklasse kan også omdefinere (skyggelegge) variable som er definert i superklassen. MEN: Dette bør IKKE brukes!!! Sjelden nødvendig Reduserer lesbarheten Kan føre til uventet oppførsel Og mer trenger dere ikke å vite om det 42
Resten av foilene er ekstra eksempler Eksempel: Lese fra forskjellige enheter class Leser { public... lesenkommando() {... <Generelle metoder som hjelper til med å tolke kommandoer> class TerminalLeser extends Leser { public... lesenkommando() {... class FilLeser extends Leser{ public... lesenkommando() {... Kanskje klassen Leser skal vær abstrakt (men det lærer vi først om senere) 43
Eksempel: Lenkete lister (mer om tre uker) (ikke i oblig 1) settinn( ) taut( ) settinn( ) taut( ) class StandardLenketListe settinn( ) taut( ) forste class SortertLenketListe settinn( ) taut( ) settinn( ) taut( ) forste class IndeksertSortertLenketListe forste : class DobbeltLenketSortertListe settinn( ) taut( ) settinn( ) taut( ) class LenketListeMedHalepeker settinn( ) taut( ) forste settinnsist( ) forste :? siste? (Her er det alt litt polymorfi (s.34)) 44
Klassehierarki for lenkede lister class StandardLenketListe class SortertLenketListe class LenketListeMedHalepeker class IndeksertSortertLenketListe class DobbeltLenketSortertListe?
Klassehierarki: Et eksempel fra Java-biblioteket ArrayList AttributeListt RoleList RoleUnresolvedList Oppgave: Slå opp på ArrayList i Javabiblioteket og se at de tre klassene er direkte subklasser av ArrayList (direkte naboer i klassehierarkiet) ( Direct Known Subclasses )
Klassehierarki: Enda et eksempel fra Javabiblioteket Object Throwable Exception RuntimeException IOException AWTException... og ca. 60 andre Oppgave: Slå opp i Javabiblioteket
Eksempel: class Musikk Hva skrives ut når programmet Musikk.java kjøres? class Musikk { public static void main (String[] args) { Instrument inst = new Piano(); inst.skrivdefinisjon(); class Instrument { void skrivdefinisjon () { System.out.println("Et instrument er noe man kan spille på"); class Piano extends Instrument { void skrivdefinisjon () { System.out.println("Et piano er et strengeinstrument"); 48
Musikk versjon 2 class Musikk { public static void main (String[] args) { Instrument inst = new Piano(); inst.skrivdefinisjon(); Hva skjer i dette tilfellet? class Instrument { void skrivdefinisjon () { System.out.println("Et instrument er noe man kan spille på"); class Piano extends Instrument { void skrivdefinisjon (String overskrift) { System.out.println(overskrift); System.out.println("Et piano er et strengeinstrument"); 49
Musikk versjon 3 class Musikk { public static void main (String[] args) { Instrument inst = new Piano(); inst.skrivdefinisjon(); Hva skjer her da? class Instrument { void skrivdefinisjon(string overskrift) { System.out.println(overskrift); System.out.println("Et instrument er noe man kan spille på"); class Piano extends Instrument { void skrivdefinisjon () { System.out.println("Et piano er et strengeinstrument"); 50
Musikk-eksemplene: Lærdom Når vi ser på et objekt via en superklasse-peker, mister vi vanligvis tilgang til metoder og variable som er definert i subklassen. Dersom en metode i subklassen også er definert (med samme signatur) i superklassen har vi likevel tilgang via superklasse-pekeren, fordi objektets dypeste metode brukes. Slike metoder kalles virtuelle metoder, og denne mekanismen kalles polymorfi. Det som er relevant er derfor hvilke metoder som finnes i superklassen (med hvilke parametre), men ikke nødvendigvis innholdet i metodene. Samme signatur = samme navn og nøyaktig samme parametre (inkl. returtype) 51
Flere virtuelle metoder class Vare { int pris; int prisutenmoms() { return pris; Anta: Vare v = new Vare(); v.pris = 100; int prismedmoms() { return (int) (1.25*prisUtenMoms()); SalgsVare s = new SalgsVare(); s.pris = 100; s.rabatt = 25; class SalgsVare extends Vare { int rabatt; // I prosent... Hva blir nå: int prisutenmoms() { return pris (pris*rabatt/100); v.prismedmoms() s.prismedmoms() 52
pris 100 Anta: Vare v = new Vare(); v.pris = 100; Vare v2 SalgsVare s = new SalgsVare(); s.pris = 100; s.rabatt = 20; Vare v2 = s; SalgsVare s Hva blir nå: v.prismedmoms(); s.prismedmoms(); v2.prismedmoms(); Vare v int prisutenmoms ( ) { return pris; int prismedmoms { return (int) (1.25*prisUtenMoms ( ) ); pris int prisutenmoms ( ) { return pris; int prismedmoms { return (int) (1.25*prisUtenMoms ( ) ); rabatt 100 20 int prisutenmoms ( ) { return pris (pris*rabatt/100); 53
main les Hilsen klassedatastruktur Inn fra tastatur - tekster fnavn import java.io.*; import java.util.*; class Hilsen { public static void main (String [] args) throws IOException { Scanner les= new Scanner (System.in); System.out.println( Hva heter du?"); String fnavn = les.next( ); String enavn = les.next( ); System.out.println( Etternavn: " + enavn ); System.out.println( Fornavn: " + fnavn ); >javac Hilsen.java >java Hilsen Hva heter du? Stein Gjessing Etternavn: Gjessing Fornavn: Stein > Et objekt av klassen String enavn 11 konstruktører 47 metoder pluss plass til å lagre en streng (en tekst) Gjessing String nextline() Objekt av klassen Scanner 11 konstruktører 47 metoder pluss plass til å lagre en streng (en tekst) Stein Et objekt av klassen String 54