TDDD78 Objektorientering i Java, del 3

Relevanta dokument
Viktiga programmeringsbegrepp: Kontrakt

Typhierarkier del 1 Gränssnitt, ärvning mellan gränssnitt, ärvning mellan klasser

Ärvning av implementation. Ärvning av implementation, inklusive abstrakta klasser Hur ska vi ärva? När ska vi ärva?

TDDD78, TDDE30, 729A Typhierarkier del 2 Vad krävs? Hur fungerar det?

TDDD78 Viktiga begrepp i programmering / objektorientering

TDDD78 Viktiga begrepp, del 2

TDDD78 Objektorientering i Java, del 3. Ärvning av implementation, inklusive abstrakta klasser Hur ska vi ärva? När ska vi ärva?

TDDD78 Objektorientering i Java, del 4. Hur vet man om två objekt är lika? Hur undviker man objekt och när?

Föreläsning 8 - del 2: Objektorienterad programmering - avancerat

Objektorienterad Programmering (TDDC77)

Objektorienterad Programkonstruktion. Föreläsning 2 2 nov 2016

TDDD78 Objektorientering i Java, del 2

Outline. Objektorienterad Programmering (TDDC77) Signatur. Klassen calculator. Överlagring (overloading) Arv (inheritance) Ahmed Rezine

Classes och Interfaces, Objects och References, Initialization

F8 - Arv. ID1004 Objektorienterad programmering Fredrik Kilander

Föreläsning 8. Arv. Arv (forts) Arv och abstrakta klasser

Classes och Interfaces, Objects och References Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

Länkade strukturer. (del 2)

Sammansatta datatyper Generics: Parametrisk polymorfism

UML. Översikt UML. Relationer mellan klasser. A är ett aggregerat av B:n. Kontor aggregat av Enheter. 12 olika diagramtyper, bl.a.

Objektorienterad Programmering (TDDC77)

F12 - Collections. ID1004 Objektorienterad programmering Fredrik Kilander

Föreläsning 12. Länkade listor

Outline. Objektorienterad Programmering (TDDC77) Åsidosättning. Signatur. Åsidosättning. Abstrakta klasser. Ahmed Rezine.

Datastrukturer. Arrayer. Arrayer. Arrayer. Array av arrayer. Array av arrayer

UML. Klassdiagr. Abstraktion. Relationer. Överskugg. Överlagr. Aktivitetsdiagram Typomv. Typomv. Klassdiagr. Abstraktion. Relationer.

TDA550 Objektorienterad programvaruutveckling IT, forts. kurs Övning vecka 2

Repetition av OOP- och Javabegrepp

Föreläsning 13 Innehåll

TDDD78 Objektorientering: Lagring och livstid

Repetition av OOP- och Javabegrepp

Objektorientering: Lagring och livstid

Principles of subclasses. Objekt-orienterad programmering och design Alex Gerdes, 2018

Arv: Fordonsexempel. Arv. Arv: fordonsexempel (forts) Arv: Ett exempel. En klassdefinition class A extends B {... }

TDDD78, TDDE30, 729A Typhierarkier del 3 När och hur vill vi använda dem? Några Best Practices

Listor. Koffman & Wolfgang kapitel 2, avsnitt , och 2.9

Begreppet subtyp/supertyp i Java. Mera om generik. Generik och arv. Generik och arv. Innehåll

2I1049 Föreläsning 5. Objektorientering. Objektorientering. Klasserna ordnas i en hierarki som motsvarar deras inbördes ordning

Lösningsförslag till omtentamen för TDA540 Objektorienterad Programmering

TDDD78 Introduktion till OOP i Java

Tommy Färnqvist, IDA, Linköpings universitet

Innehåll. dynamisk bindning. och programmering CRC) u Arv, polymorfi och

Objektorienterad Programmering (TDDC77)

Abstrakt klass. DD2385 Programutvecklingsteknik Några bilder till föreläsning 4 31/ Exempel: Implementation av Schackpjäser.

Inkapsling tumregler. Åtkomstmodifikatorer, instantiering, referenser, identitet och ekvivalens, samt klassvariabler. public och private

Idag. statiska metoder och variabler. private/public/protected. final, abstrakta klasser, gränssnitt, delegering. wrapper classes

Abstrakt klass. DD2385 Programutvecklingsteknik Några bilder till föreläsning 4 7/ Exempel: Implementation av Schackpjäser.

Objektorientering: Lagring, räckvidd och livstid

Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 4 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Outline. Objektorienterad Programmering (TDDC77) Att instansiera en klass. Objekt. Instansiering. Åtkomst. Abstrakt datatyp.

Subklasser och arv Inledning till grafik (JFrame och JPanel). Något om interface. Objektorienterad programvaruutveckling GU (DIT011) Subklasser

public interface Skrivbar { void skriv(); } public class Punkt implements Skrivbar { public double x; public double y;

Interface. Interface. Tobias Wrigstad (baserat på bilder från Tom Smedsaas) 3 december 2010

DAT043 - föreläsning 8

Konstruktion av klasser med klasser

Outline. Objektorienterad Programmering (TDDC77) Laborationsserie del två. Vad händer under HT2. Introduktion HT2 UML.

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 2 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Ett problem. Kontrollstrukturer och arrayer. Arrayer. Lösningen. Arrayer och hakparanteser. Exempel int[] results; results = new int[10]; // 0..

Generisk klass med typparameter Inre klass - ListIterator

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 6 Erik Nilsson, Institutionen för Datavetenskap, LiU

Exempel på användning av arv: Geometriska figurer

Principles of subclasses Objekt-orienterad programmering och design (DIT953) Niklas Broberg, 2018

DAT043 - Föreläsning 7

Exempel. Arrayer. Lösningen. Ett problem. Arrayer och hakparanteser. Arrayer

Abstrakt datatyp. -Algoritmer och Datastrukturer- För utveckling av verksamhet, produkter och livskvalitet.

TDDE10 TDDE11, 725G90. Objektorienterad programmering i Java, Föreläsning 3 Erik Nilsson, Institutionen för Datavetenskap, LiU

TENTAMEN OOP

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 2 Erik Nilsson, Institutionen för Datavetenskap, LiU

TDDD78 Introduktion till OOP i Java

Föreläsning 4. Klass. Klassdeklaration. Klasser Och Objekt

OOP Objekt-orienterad programmering

OOMPA 2D1359 Föreläsning 8

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 4 Erik Nilsson, Institutionen för Datavetenskap, LiU

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

TDDD78 Introduktion till OOP i Java

Arv. Fundamental objekt-orienterad teknik. arv i Java modifieraren protected Lägga till och modifiera metoder med hjälp av arv Klass hierarkier

"Är en"-relation. "Har en"-relation. Arv. Seminarium 2 Relevanta uppgifter. I exemplet Boll från förra föreläsningen gällde

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

UML. Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

TDDD78 Objektorientering i Java, del 2

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 6 Erik Nilsson, Institutionen för Datavetenskap, LiU

Klasshierarkier - repetition

I STONE. I Variabler, datatyper, typkonvertering. I Logiska och matematiska uttryck. I Metoder-returvärde och parametrar. I Villkorssatser if/else

Klasshierarkier. Klasser kan byggas på redan definierade klasser

public och private Obs: private inte skyddar mot access från andra objekt i samma klass.

LÖSNINGSFÖRSLAG

Omtentamen för TDA540 Objektorienterad Programmering. Institutionen för Datavetenskap CTH HT-17, TDA540. Dag: , Tid:

Monday, November 16, Senaste Labben

Instuderingsuppgifter läsvecka 2

Föreläsning 5-6 Innehåll. Exempel på program med objekt. Exempel: kvadratobjekt. Objekt. Skapa och använda objekt Skriva egna klasser

OOP Objekt-orienterad programmering

Föreläsning 4 Innehåll. Abstrakta datatypen lista. Implementering av listor. Abstrakt datatypen lista. Abstrakt datatyp

OOP Objekt-orienterad programmering

Föreläsning 5-6 Innehåll

Kopiering av objekt i Java

F9 - Polymorfism. ID1004 Objektorienterad programmering Fredrik Kilander

Objekt, klasser. Tillstånd Signatur Kommunikation Typ. Fält, parametrar och lokala variabler. Konstruktorer Metoder DAVA15

Samlingar Collection classes

Föreläsning 2. Länkad lista och iterator

TENTAMEN I DATAVETENSKAP

Transkript:

TDDD78 Objektorientering i Java, del 3 Ärvning av implementation, inklusive abstrakta klasser Egenskaper hos Javas arvshierarki Att skriva kontrakt, och dess konsekvenser Att gömma information i ett objekt jonas.kvarnstrom@liu.se 2016

Implementationsarv 1: Klassnivåer Nu kan vi ha godtyckligt antal nivåer Collection <<interface>> 2 size(): int add(object element): Object Set <<interface>> size(): int add(object element): Object List <<interface>> size(): int get(int pos): Object add(object element): Object set(int index, Object element): void men bara en klassnivå. Vill vi ha mer? Varför? LinkedList ArrayList SkipList

Implementationsarv 2: Nya medlemmar 3 En anledning: Addera funktionalitet till en klass Kan inte ändra Circle-klassen men vill ha en variation som kan rita ut sig själv public class GraphicCircle extends Circle { private Color outline, fill; public GraphicCircle(double x, double y, double r, Color outline, Color fill) { super(x, y, r); // Explained soon this.outline = outline; this.fill = fill; public void draw(drawwindow dw) { dw.drawcircle(x, y, r, outline, fill); Ärver allt från Circle: x, y, r, getradius() Kan addera: outline, fill, draw() GraphicCircle utökar eller ärver från Circle GraphicCircle är en subklass till Circle Circle är en superklass till GraphicCircle

Implementationsarv 3: Visualisering 4 Circle c = new Circle(1, 2, 3); Circle gc = new GraphicCircle(10, 11, 12, Color.GRAY, Color.BLACK); Circle: c Circle: gc Object (data) header: x 1 y 2 r 3 Object (data) header: x 10 y 11 r 12 fill outline Circle getcircum getarea setradius GraphicCircle getcircum getarea setradius draw code code code code code code code [Color-objekt: GRAY] [Color-objekt: BLACK]

Implementationsarv 4: Overriding 5 Anledning 2: Ändra eller utöka nedärvd funktionalitet Vi har en Label-klass som ritar ut text class Label extends Component { public void paint() { // rita ut texten Vi vill skapa ett textfält, som också ritar ut en markör class TextField extends Label { public void paint() { super.paint(); // Paint the text paintcursor(); // Paint the cursor Den "gamla" implementationen kan anropas med super.foo(): "Den närmaste foo() ovanför mig Kan override:a ("ersätta") metoder: Ge dem en ny implementation Kräver identiska parametertyper annars blir det overloading

UML-klassdiagram: Generalisering Klassrelation: Generalisering (ärvning) Som för gränssnitt 6 +x, y, r: double +getarea(): double Circle +outline, fill: Color GraphicCircle +draw(drawwindow): void

Annoteringar vid overriding 7 Java: Kan ange "extra information om koden" via annoteringar Exempel: @override kan stoppas in automatiskt av IDEA class ArrayList { public Object get(int index) { class DebugArrayList extends ArrayList { @Override public Object get(int index) { System.out.println( "Getting object at index " + index); return super.get(index); Den här implementationen ersätter en annan! Stava fel, använd fel typer, ta bort get() från superklassen kompileringsfel!

Konstruktorer och arv 1 Med implementationsarv: Ett objekt har "flera delar" Hur initialiseras de? 9 Object (data) header: x 0 y 0 r 0 outline fill Kommer från Circle Kommer från GraphicCircle ("Kryssen" indikerar att värdet är null)

Konstruktorer och arv 2 10 När vi anropar new GraphicCircle(1.0, 2.0, 3.0, c1, c2); Först: minnesallokering, defaultvärden För alla fält Ingen får komma åt "gammalt skräp" Object (data) header: x 0 y 0 r 0 outline fill Sedan: Måste låta GraphicCircle-delen "konstruera sig" Måste låta Circle-delen "konstruera sig" I vilken ordning?

Konstruktorer och arv 3 Konstruera "superklass-delen" av objektet först! Ingen får komma åt Circle fälten innan Circle initialiserat dem Inte ens dess egen subklass! Men vi anropade ju new GraphicCircle(1.0, 2.0, 3.0, c1, c2); 11 GraphicCircle(double x, double y, double r, Color outline, Color fill) { super(x, y, r); this.outline = outline; this.fill = fill; Det första GraphicCircle gör: Anropa superklassens konstruktor Sedan: Initialiserar sin "egen" del GraphicCircle(double x, double y, double r, Color outline, Color fill) { this.outline = outline; this.fill = fill; Strunta i super( ) kompilatorn stoppar in super() utan argument Nu finns inte Circle() : Kompileringsfel!

Sammanfattning 1. Allokera minne och nollställ Sedan kan konstruktorer komma åt minnet Ingen kan komma åt "gammalt skräp" i minnet 12 2. Konstruktorn för Circle Sedan kan subklassens konstruktor komma åt objektet Ingen kan komma åt Circle-delen innan Circle fått säga sitt 3. Konstruktorn för GraphicCircle Sedan kan anropande koden komma åt objektet Ingen kan komma åt en GraphicCircle innan den fått säga sitt

Motivation Anta en uppsättning relaterade klasser Bör antagligen ha ett gemensamt gränssnitt 14 List ArrayList LinkedList Men hur gör vi med själva implementationen?

Abstract 1: Duplicerad kod 15 class A ArrayList lot of common implements code! List { List Object[] elements = new Object[42]; int length length = field 0; int size(), { return indexof() length; ArrayList LinkedList Object get(int index) { return elements[index]; void add(object element) { void set(int index, Object element) { class LinkedList implements List { int indexof(object o) { for (int i = 0; i < length; i++) if (get(i).equals(o)) return i; return 1; Massor av duplicerad kod Hur kan vi använda samma kod för båda klasser? Node head = null, tail = null; int length = 0; int size() { return length; Object get(int index) { void add(object element) { void set(int index, Object element) { int indexof(object o) { for (int i = 0; i < length; i++) if (get(i).equals(o)) return i; return 1;

Abstract 2: Återanvända med gränssnitt? 16 interface List { int length = 0; int size() { return length; int indexof(object o) { for (int i = 0; i < length; i++) if (get(i).equals(o)) return i; return 1; ArrayList List LinkedList Bra försök, men gränssnitt kan inte innehålla fält (eller metoder, i Java 7) class ArrayList implements List { Object[] elements = new Object[42]; Object get(int index) { return elements[index]; void add(object element) { void set(int index, Object element) { class LinkedList implements List { Node head = null, tail = null; Object get(int index) { void add(object element) { void set(int index, Object element) {

Abstract 3: Återanvända med konkret klass? 17 class GenericList implements List { int length = 0; int size() { return length; int indexof(object o) { for (int i = 0; i < length; i++) if (get(i).equals(o)) return i; return 1; List Bra försök, men GenericList skulle behöva implementera add(), get(), set()! class ArrayList extends GenericList { Object[] elements = new Object[42]; Object get(final int index) { return elements[index]; void add(final Object element) { void set(int index, Object element) { ArrayList GenericList LinkedList class LinkedList extends GenericList { Node head = null, tail = null; Object get(final int index) { void add(final Object element) { void set(int index, Object element) {

Abstract 4: Dummy-implementation? 18 class GenericList implements List { Bra försök, men GenericList skulle int length = 0; inte uppfylla kraven på List: int size() { return length; get ska returnera rätt element! int indexof(object o) { for (int i = 0; i < length; i++) if (get(i).equals(o)) return i; return 1; class ArrayList extends GenericList { Object[] elements = new Object[42]; Object get(final int index) { Object get(final int index) { return elements[index]; return null; void add(final Object element) { List void set(int index, Object element) { void add(final Object element) { GenericList class LinkedList extends GenericList { Node head = null, tail = null; Object get(final int index) { void add(final Object element) { ArrayList LinkedList void set(int index, Object element) {

Abstract 5: Återanvända med abstrakt klass! 19 abstract class GenericList implements List { protected int length = 0; public int size() { return length; public int indexof(object o) { for (int i = 0; i < length; i++) if (get(i).equals(o)) return i; return 1; List Abstrakta klasser är delvis implementerade Abstract kan inte instansieras med new GenericList() public class ArrayList extends GenericList { public Object[] elements = new Object[42]; public Object get(final int index) { public void add(final Object element) { public void set(int index, Object element) { ArrayList GenericList LinkedList public class LinkedList extends GenericList { public Node head = null, tail = null; public Object get(final int index) { public void add(final Object element) { public void set(int index, Object element) {

Konstruktorer i abstrakta klasser Även en abstrakt klass måste kunna initialisera sina objekt 20 abstract class GenericList implements List { protected int length; protected GenericList() { this.length = 0; public int size() { return length; public int indexof(object obj) { for (int i = 0; i < length; i++) if (get(i).equals(obj)) return i; return 1; Det finns fält som ärvs av ArrayList, Vi kan initialisera dem i en konstruktor: Klassen bestämmer över sina objekt Men hur anropas konstruktorn? Inte med new GenericList()!

Konstruktorer i abstrakta klasser (2) 21 abstract class GenericList implements List { protected int length; protected GenericList() { this.length = 0; public int size() { return length; public int indexof(object obj) { for (int i = 0; i < length; i++) if (get(i).equals(obj)) return i; return 1; class ArrayList extends GenericList { Object[] elements; ArrayList() { super(); this.elements = new Object[42]; Vi kan anropa new ArrayList()! Detta måste anropa superklassens konstruktor

Definition: Multipel ärvning Multipel ärvning: Utöka mer än en klass Kan vara användbart, men även förvirrande 23 GenericList ArrayTools Om båda superklasser har implementerat isempty() ArrayList Vilken ska ärvas ner till ArrayList? ArrayList list = new ArrayList(); list.add(foo); if (list.isempty()) { // Vilken isempty() anropas?...

Multipel ärvning i Java? Java använder enkel ärvning (single inheritance) En klass kan bara utöka en superklass 24 GenericList ArrayList Gränssnitt är ett undantag innehåller ingen kod Klasser kan implementera flera gränssnitt (måste uppfylla flera kontrakt!) Gränssnitt kan utöka flera (super-)gränssnitt Sortable List SortableList

Rötter i klasshierarkin I vissa språk kan klasshierarkin ha flera rötter Vissa klasser är relaterade via ärvning Andra är helt fristående 25 Thread Component String AbstractCollection Container AbstractList Button ArrayList Om vi då vill kunna skicka in antingen String eller Thread: Omöjligt!

Enkelrotad klasshierarki Alla Java-klasser är subklasser till java.lang.object! 26 Utan extends class GenericList { Är ekvivalent med class GenericList extends Object { Med extends class DebugList extends MyList { class MyList extends ArrayList { class ArrayList extends GenericList { class GenericList { Så småningom kommer vi till Object!

Enkelrotad klasshierarki (2) 27 Fördel: En Object-variabel kan peka på vilket objekt som helst Många sammansatta datatyper drar nytta av detta: Set, List osv. lagrar Object Klassen Object har några fördefinierade metoder Tillgängliga i alla objekt (Men inga fält) Object Thread Component String AbstractCollection Container AbstractList Button ArrayList

Metoder i Object överkurs! 28 public class Object { public final native Class<?> getclass(); // Vilken klass tillhör du? public native int hashcode(); public boolean equals(object obj); protected native Object clone(); public String tostring(); // (Överkurs) // Är du lika med ett annat objekt? // Skapa en kopia (knepigt att använda rätt!) // Strängrepresentation av objektet public final native void notify(); // För trådhantering public final native void notifyall(); public final native void wait(long timeout) throws InterruptedException; public final void wait(long timeout, int nanos) throws InterruptedException; public final void wait() throws InterruptedException; protected void finalize() // Kan anropas när objektet slängs bort // (knepigt att använda; inte en destruktor)

Sammanfattning: Klasshierarkier 30 Collection 2. Ett gränssnitt kan ärva från och utöka (löftena som gavs av) ett annat gränssnitt Sortable Set List 1. Ofta (men inte alltid) har vi en mängd gränssnitt som definierar funktionalitet och ger löften (kontrakt), bland annat genom att ange abstrakta metoder

Sammanfattning: Klasshierarkier (2) 31 Collection 3. En metod kan ta "godtycklig Collection" som parameter Sortable Set List 2. En metod kan ta godtycklig List som parameter. Kan vara en SkipList eller CheckedList spelar ingen roll! SkipList 4. En klass kan implementera flera gränssnitt. Ingen tvetydighet, eftersom ingen kod ärvs. CheckedList 1. Klasser kan implementera gränssnitt måste uppfylla deras kontrakt

Sammanfattning: Klasshierarkier (3) Collection 32 Sortable Set List 1. Abstrakta klasser (GenericList) can tillhandahålla partiella implementationer där vissa metoder är abstrakta ("löften" att metoden ska finnas) SkipList CheckedList GenericList 2. och kan ha konkreta subklasser som implementerar den saknade funktionaliteten ArrayList LinkedList

Sammanfattning: Klasshierarkier (4) Collection 33 Sortable Set List En del klasser, som MyList, implementerar inga gränssnitt alls SkipList CheckedList GenericList MyList ArrayList LinkedList

Sammanfattning: Klasshierarkier (5) Collection 34 Object Sortable Set List SkipList CheckedList GenericList String ArrayList LinkedList men alla klasser utökar (direkt eller indirekt) java.lang.object!

jonas.kvarnstrom@liu.se 2016 Viktiga programmeringsbegrepp: Kontrakt Vad lovar {klassen, metoden, fältet?

Kontrakt Kontrakt: Överenskommelse som anger Vad som ska tillhandahållas Vad som förväntas i utbyte Allmänna regler runt utbytet 36 Inom objektorienterad programmering: Vilka värden kan en metod ta emot? Vad garanterar metoden att den gör, om den får sådana värden? Vad returnerar den? Vad garanterar en klass angående sitt tillstånd och beteende?

Kod kan innehålla (vissa) formella kontrakt 37 class Circle { private double x, y, r; public Circle(double x, double y, double r) { this.x = x; this.y = y; this.r = r; public double getarea() { return Math.PI * this.r * this.r ; Krav på input: Parametrarna måste vara av typ double Löfte om resultattyp: Returnerar alltid double Följer direkt från manifest typning Så vanligt att man oftast inte ens ser det som kontrakt

Varför räcker inte koden? 38 class Circle { private double x, y, r; public Circle(double x, double y, double r) { this.x = x; this.y = y; this.r = r; public double getarea() { return Math.PI * this.r * this.r ; + Definierar exakt vad programmet gör! Varför räcker inte detta?

Varför räcker inte koden? (2) 39 class Circle { private double x, y, r; public Circle(double x, double y, double r) { this.x = x; this.y = y; this.r = r; public double getarea() { return Math.PI * this.r * this.r ; Svårt att inse alla konsekvenser av tusentals rader kod + Kontraktet bör sammanfatta vad som garanteras, krävs

Varför räcker inte koden? (3) Vi är inte intresserade av vad koden gör! Mycket viktig konceptuell skillnad mellan: 40 Vad vi faktiskt gör (koden) Implementationsdetaljer Implementationsdetaljer Vad vi lovar att göra, och att fortsätta göra i all evighet (kontraktet) Buggar Buggar

Exempel 1: Sortering Exempel: Sortera namn Input: [A Z:son, E X:son, B Y:son, C Y:son, D Z:son] Nu vill vi sortera: Primärt på efternamn Sekundärt, vid samma efternamn på förnamn Vi vill alltså få: [E X:son, B Y:son, C Y:son, A Z:son, D Z:son] 41 Samma efternamn Samma efternamn

Exempel 1: Metod En metod: Börja med en lista [A Z:son, E X:son, B Y:son, C Y:son, D Z:son] Sortera på förnamn utan att tänka på efternamn [A Z:son, B Y:son, C Y:son, D Z:son, E X:son] 42 Sortera på efternamn utan att tänka på förnamn 4 möjliga resultat, samtliga XYYZZ: [E X:son, B Y:son, C Y:son, A Z:son, D Z:son] [E X:son, C Y:son, B Y:son, A Z:son, D Z:son] [E X:son, B Y:son, C Y:son, D Z:son, A Z:son] [E X:son, C Y:son, B Y:son, D Z:son, A Z:son] Vi tänker bara på efternamn Namn med samma förnamn kan kastas om Med stabil sortering: Byt bara ordning på två element om det krävs [E X:son, B Y:son, C Y:son, A Z:son, D Z:son] B Y:son fortfarande före C Y:son A Z:son fortfarande före D Z:son Löser vårt problem!

Exempel 1: Vad kan vi se i koden? Anta sorteringsmetoden saknar kontrakt Måste läsa koden public class List { private String[] strings; public void sort() { for (int i = 0; i < strings.length - 1; i++) { for (int j = 1; j < strings.length - i; j++) { if (strings[j - 1].compareTo(strings[j]) > 0) { String temp = strings[j - 1]; strings[j - 1] = strings[j]; strings[j] = temp; 43 Aha den sorteringen är stabil! Då utnyttjar vi det!

Exempel 1: Vad är tillåtet? Senare: Någon vill förbättra listklassen! Sorteringen var ineffektiv 44 Om vi har detta Får vi skriva om så här? public class List { public class List { public void sort() { // Utför bubble sort // (råkar vara stabil) public void sort() { // Utför heap sort // (snabbare, men inte stabil) // Andra kanske förlitar sig på egenskaper koden "råkade" ha dilemma!

Kontrakt 1 Undvik genom kontrakt! Vissa språk har formellt stöd t.ex. Eiffel set_hour (new_hour: INTEGER) -- Set `hour' to `new_hour' require valid_argument: 0 <= new_hour and new_hour <= 23 do hour := new_hour ensure hour_set: hour = new_hour end 45 precondition postcondition Ofta får man istället använda dokumentationen Idealet: Bara det som står i kontraktet gäller titta aldrig på koden! class List { /** Sorterar listan efter ordlängd. */ void sort() { Här står inget om stabilitet. Då kan vi inte förutsätta det!

Kontrakt 2 Ju tydligare, desto bättre 46 class List { /** Sorterar listan efter ordlängd. Stabilitet garanteras inte. */ void sort() { Beskriv gärna mer om vad koden lovar och inte lovar

Exempel 2: Vad utlovas? Får jag ("Cirkel-användare") skicka in en negativ radie här? Ser inget som skulle orsaka problem Men vem vet hur klassen kan ändras i framtiden? 47 class Circle { double x, y, r; Circle(double x, double y, double r) { this.x = x; this.y = y; this.r = r;

Exempel 2: Vad är tillåtet? Får jag ("Cirkel-utvecklare") ändra min kod så här? Verkar rimligt att cirklar ska ha positiv radie Men kod som förut fungerade kommer nu att krascha! 48 class Circle { double x, y, r; class Circle { double x, y, r; Circle(double x, double y, double r) { this.x = x; this.y = y; this.r = r; Circle(double x, double y, double r) { if (r <= 0.0) throw ; this.x = x; this.y = y; this.r = r;

Exempel 2: Kontrakt? Med kontrakttänkande: 49 class Circle { double x, y, r; /** Skapar en cirkel med angivna koordinater och radie. */ Circle(double x, double y, double r) { this.x = x; this.y = y; this.r = r; Metoden tar emot double. Det står inget om begränsningar. Alltså lovar den att klara godtycklig double.

Exempel 2: Kontrakt? Med kontrakttänkande: 50 class Circle { double x, y, r; /** Skapar en cirkel med angivna koordinater och radie. Radien måste vara strikt positiv. */ Circle(double x, double y, double r) { this.x = x; this.y = y; this.r = r; Lovar att klara strikt positiva radier. Kräver sådan input. Skickar du in annat är beteendet odefinierat (kan krascha, )

Grundregel för kontrakt: Dokumentera alltid vad koden kräver och vad den lovar

Relaterad grundregel: Dokumentera inte vad koden gör utan vad den ska göra (och gärna varför) Vi återkommer till kontrakt och löften flera gånger!

Krav på hierarkier 1 54 List size(): int get(int pos): Object add(object element): Object set(int pos, Object element): void LinkedList ArrayList SkipList size(): int get(int pos): Object add(object element): Object -- ingen set Får subtypen LinkedList sakna metoder från List?

Krav på hierarkier 2 55 List size(): int get(int pos): Object add(object element): Object set(int pos, Object element): void LinkedList ArrayList SkipList size(): int get(int pos): Object add(object element): Object set(int pos, Object element): void Om List.add() lägger till i slutet, får LinkedList.add() lägga till i början?

Krav på hierarkier 3 56 Även List har ett kontrakt En ArrayList är en List måste uppfylla samma kontrakt! (Fåglar har fjädrar, ankor är fåglar ankor har fjädrar) Subtypens eget kontrakt får bara: Lova mer ge starkare garantier (ankor kan kvacka) Kräva mindre ha svagare krav Det är detta som garanterar: Om vi accepterar en List, är vi nöjda med vilken subtyp som helst! void quicksort(list somelist) { // Vi programmerar // utifrån List:s kontrakt // Detta uppfylls oavsett om vi får en // ArrayList, SkipList, LinkedList,

Krav på hierarkier 4: LSP En formell beskrivning: Liskov Substitution Principle Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S, where S is a subtype of T. 57 Om vi kan bevisa något om alla List-objekt, måste detta även gälla för alla LinkedList-objekt. Barbara Liskov

Kovarianta returtyper! LSP säger: Subtypens eget kontrakt får bara: Lova mer ge starkare garantier Kräva mindre ha svagare krav 59 En subklass kan stärka löftet om returtyp public interface List { List makecopy(); List convert(); public class ArrayList implements List { ArrayList makecopy() { SkipList convert() { Varierar "åt samma håll" (en specialisering av List specialiserar även returtyperna) kovariant

Kontravarianta parametertyper? LSP säger: Subtypens eget kontrakt får bara: Lova mer ge starkare garantier Kräva mindre ha svagare krav 60 Kan en subklass ställa svagare krav på parametertyp? public interface List extends Collection { void addall(list other); public class ArrayList implements List { void addall(collection other) { Varierar "åt motsatt håll" kontravariant Inte tillåtet i Java: Resulterar i overloading (två varianter av metoden)

Information Hiding Encapsulation

Bakgrund Tänk er en lista som garanterar att elementen är i sorterad ordning! 62 class SortedList { String[] elements; int size; String get(int pos) { return void add(string el) { int pos = findnewpositionfor(el); insertat(pos, el); Lagring för alla element Hämtar element Stoppar in element på rätt plats int findnewpositionfor(string el) { void insertat(int pos, String el) { med dessa hjälpmetoder

Att gömma information Ofta vill vi gömma delar av klasser och objekt 63 class SortedList { String[] elements; int size; int findnewpositionfor(string el) { void insertat(int pos, String el) { String get(int pos) { return Syns bara inuti själva klassen void add(string el) { int pos = findnewpositionfor(el); insertat(pos, el); Synligt utåt

Gömma: För att inte förvirra användarna Mindre synligt mer överskådligt 64 class SortedList { String[] elements; int size; int findnewpositionfor(string el) { void insertat(int pos, String el) { String get(int pos) { return Användaren behöver aldrig anropa findnewpos eller insertat Att de syns förvirrar, gör klassen oöverskådlig! void add(string el) { int pos = findnewpositionfor(el); insertat(pos, el); Detta måste användarna känna till för att använda klassen

Gömma: Minska åtaganden (kontrakt) 65 Det vi har visat upp, måste vi normalt ha kvar Blir del av kontraktet class SortedList { String[] elements; int size; int findnewpositionfor(string el) { void insertat(int pos, String el) { String get(int pos) { return Användarna behöver inte komma åt element via list.elements! Göm det enbart get/add används vi kan byta ut resten om vi vill frihet! void add(string el) { int pos = findnewpositionfor(el); insertat(pos, el); Detta ska utnyttjas av användarna, måste visas och finnas kvar

Gömma: Minska åtaganden (kontrakt) 66 Det vi har visat upp, måste vi normalt ha kvar Blir del av kontraktet class SortedList { String[] elements; int size; int findnewpositionfor(string el) { void insertat(int pos, String el) { Användarna behöver inte komma åt element via list.elements! Göm det enbart get/add används String get(int class SortedList pos) { return { vi kan byta ut resten om vi vill! ListNode first; void add(string ListNode el) findnewpositionfor(string { el) { Detta ska utnyttjas int pos = findnewpositionfor(el); void insertelementat(listnode pos, String el) { av användarna, insertat(pos, String el); get(int pos) { return måste Alternativ visas void add(string el) { och implementation, finnas kvar där ListNode pos = findnewpositionfor(el); insertelementat(pos, el); den "publika" delen har kvar samma signatur

Gömma: För att uppfylla vårt kontrakt 67 /** * This class maintains a sorted list of elements. * As long as the contents of an element does not change, * elements will always be in sorted order. */ class SortedList { String[] elements; int size; int findnewpositionfor(string el) { void insertat(int pos, String el) { void add(string el) { int pos = findnewpositionfor(el); insertat(pos, el); Om användare kan anropa insertat med fel position blir listan osorterad Då bryter vi vårt löfte!

Hur gömmer vi information?

Att gömma data i Java Många OO-språk tillåter oss att gömma data I Java kan klasser, gränssnitt, fält och metoder vara: public alla har tillgång protected [nothing] private tillgång i underklasser + andra i samma paket tillgång i samma paket (används sällan) tillgång inom samma klass 69 public class SortedList { private String[] elements; private int size; private int findnewpositionfor(string el) { private void insertelementat(int pos, String el) { public void add(string el) { int pos = findnewpositionfor(el); insertelementat(pos, el); Vad hade private betytt utan OO? Vi lovar mindre i vårt kontrakt! Skapa ett stabilt gränssnitt för "allmänheten": add() Göm all info om implementationsdetaljer

Inkapsling 70 Två betydelser hos Inkapsling (Encapsulation) Koppla ihop data och funktioner Fundamentalt i OO Objekt: en kapsel som innehåller både data och funktioner Begränsa tillgång till medlemmar Genom accessmodifierare Vissa medlemmar är instängda i en ogenomskinlig kapsel, och kan inte ses eller utnytttjas från utsidan

Privata fält 71 Vanlig princip: Fält är implementationsdetaljer, ska vara privata Om det verkligen är rimligt att andra klasser ska komma åt fältvärden: Skapa en public accessor-metod (getter) vid behov Skapa en public mutator-metod (setter) vid behov Kan ändra intern representation: Ändra bara getter/setter, som är i samma klass private double diameter; /** Set the radius to r (must not be negative). */ public void setradius(final double radius) { if (r >= 0.0) diameter = 2 * radius; else throw new IllegalArgumentException("Negative radius: " + r); Kan lägga till konsistenskontroll

Namngivning: Getter, Setter Namngivning: 72 private double radius; private boolean visible; /** Set the radius to r (must not be negative). */ public void setradius(final double r) { if (radius >= 0.0) radius = r; else throw new ; public double getradius() { return radius; public boolean isvisible() { return visible; Setters: void setproperty( ) Getters: getproperty() Booleska getters: isproperty() Mer info: http://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html

Tillåtna publika fält Vissa anser att det finns undantag Rena datastrukturer (inte mycket beteende, osannolikt att det skulle ändras i framtiden) 73 public class Dimension { public int width; public int height;

Konstruktorer i abstrakta klasser 74 abstract class GenericList implements List { protected int length; protected GenericList() { this.length = 0; public int size() { return length; public int indexof(object obj) { for (int i = 0; i < length; i++) if (get(i).equals(obj)) return i; return 1; Konstruktorer i abstrakta klasser kan vara protected: Tillgängliga i subklasser