Föreläsning 5. När skall man använda implementationsarv? När skall man använda implementationsarv?

Relevanta dokument
Föreläsning 5. När skall man använda implementationsarv?

Föreläsning 5. När skall implementationsarv användas? The Open-Closed Principle (OCP) Liskov Substitution Principle (LSP)

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

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

JUnit. Ska kompletteras med kodexempel på JUnit. DD2385 Programutvecklingsteknik Några bilder till föreläsning 12 21/5 2012

Instuderingsuppgifter läsvecka 2

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

Generics och polymorfism. Objekt-orienterad programmering och design (DIT953) Niklas Broberg / Johannes Åman Pohjola, 2018

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

Tentamen. 2D4135 vt 2004 Objektorienterad programmering, design och analys med Java Torsdagen den 3 juni 2004 kl

Objektorienterad programmering. Grundläggande begrepp

Grundläggande programmering, STS 1, VT Sven Sandberg. Föreläsning 14

Föreläsning 13 Innehåll

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

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

Static vs Dynamic binding Polymorfism. Objekt-orienterad programmering och design (DIT953) Niklas Broberg, 2018

Objektorienterad Programmering (TDDC77)

Objektorientering - Arv och polymorfi. Eric Elfving Institutionen för datavetenskap

TDDC76 - Programmering och Datastrukturer

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

Separation of Concern. Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016 Johannes Åman Pohjola, 2017

Static vs Dynamic binding Polymorfism. Objekt-orienterad programmering och design Alex Gerdes, 2016

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

Laboration 1: Figurer i hierarki

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

Arv innebär att man skapar en ny klass (subklass) utifrån en redan existerande klass (superklass, basklass).

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

PROGRAMMERINGSTEKNIK TIN212

Objekt-orienterad Programmering och Design. TDA551 Alex Gerdes, HT-2016

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

Separation of Concern. Objekt-orienterad programmering och design (DIT953) Niklas Broberg / Johannes Åman Pohjola, 2018

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

F8 - Arv. ID1004 Objektorienterad programmering Fredrik Kilander

Objektorienterad Programmering (TDDC77)

Objektorienterad Programmering (TDDC77)

Objekt-orienterad programmering och design. DIT953 Niklas Broberg, 2018

Exempel på användning av arv: Geometriska figurer

Ett objekt... Exempel: Om ni tittar er runt i föreläsningssalen ser in många olika fysiska föremål:

Kursombud. Objektorienterad modellering och diskreta strukturer / design. Agile? Designprinciper EDAF10 EDA061. Lennart Andersson. Grupper för projekt

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

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

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

Tentamen i Objektorienterad modellering och design

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

Föreläsning 5. Föreläsning 5. Klasser och objekt. Klasser och objekt. Klasser och objekt

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

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

Föreläsning 8 Programmeringsteknik och Matlab DD1312. Klassmetod. Egen modul

Classes och Interfaces, Objects och References, Initialization

Återanvändning. Två mekanismer. Nedärvning av egenskaper (inheritance) Objekt komposition

Föreläsning 5. Föreläsning 5

Klasser och objekt. Henrik Johansson. August 20, 2008

Objektorienterad programmering Föreläsning 8. Copyright Mahmud Al Hakim Agenda (halvdag)

Imperativ programmering. Föreläsning 4

Dependencies High cohesion, low coupling. Objekt-orienterad programmering och design (DIT953) Niklas Broberg, 2018

Introduktion till arv

Tentamen i Objektorienterad modellering och design Helsingborg

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

Arv och polymorfism i Java

Arv. Objektorienterad och komponentbaserad programmering

Svaret kan ges i Javakod (eller i UML-klassdiagram). public class A { B minb;... } public class B { <B:s många variabler och metoder> } Lösning:

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

Dependencies High cohesion, low coupling. Objekt-orienterad programmering och design Alex Gerdes, 2018

Abstrakta Klasser 2. Kodning är bara en liten del i programvaruutvecklingen 6% 1% 6% Abstrakta Klasser - deklaration. Programutveckling sker i faser

public class BoundedCounter {

Introduktion och OO. Objekt-orienterad Programmering och Design (TDA552) Alex Gerdes, HT-2018

Sammanfattning och Tentamensinfo Objekt-orienterad programmering och design (DIT953) Niklas Broberg, 2018

Viktiga programmeringsbegrepp: Kontrakt

F9 - Polymorfism. ID1004 Objektorienterad programmering Fredrik Kilander

Objekt-orienterad Programmering och Design. TDA552 Alex Gerdes, HT-2018

Lösningar till tentamen i EDAF25

Subtyping, co- och contra-variance. Objekt-orienterad programmering och design Alex Gerdes, 2016

Målen med OOSU. Objektorienterad programmering. Objektorienterad programmering. Karlstads Universitet, Johan Öfverberg 1

SOLID är en akronym för fem stycken designprinciper som används vid mjukvaruutveckling. SOLID står för:

Generic type declarations. Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

Kopiering av objekt i Java

Mjukvarudesign. Designprocessen. Teknisk design. Konceptuell design

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

Lösningar till Fiktiv Tentamen på kursen. 2D4135 Objektorienterad programmering, design och analys med Java vt2004. Teoridel

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

OOMPA 2D1359 Föreläsning 2

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

Tentamen. DD2385 Programutvecklingsteknik vt 2013 Onsdagen den 22 maj 2013 kl Hjälpmedel: penna, suddgummi, linjal

Föreläsning 3 Arvsmekanismen Variabler och typer Typer och subtyper

Föreläsning 4. Polymorfism. Polymorfism Dynamisk bindning Inkapsling Information hiding Access-metoder och mutator-metoder

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

Föreläsning 5-6 Innehåll

Systemvetarutbildningen och dataekonomutbildningen

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

DAT043 - Föreläsning 7

Repetition av viktiga begrepp inom objektorienterad programmering

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

Föreläsning 15: Repetition DVGA02

TDA550 Objektorienterad programmering, fortsättningskurs. Föreläsning 1. Introduktion Variabler och typer

Static vs Dynamic binding Override vs Overload. Objekt-orienterad programmering och design Alex Gerdes och Sólrún Halla Einarsdóttir, 2018

Objektorienterad programmering (OOP) Föreläsning 15 & 16. Klasser för olika slags fordon. Klasser och objekt

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

Tentamen i Objektorienterad modellering och design Helsingborg

Föreläsning 4. Klasser och objekt

Transkript:

När skall man använda implementationsarv? Föreläsning 5 När skall implementationsarv användas? The Open-Closed Principle (OCP) Liskov Substitution Principle (LSP) Implementationsarv är en konstruktion som kan användas för att få elegant kod - lättläst - tydlig - utbyggbar - återanvändbar Men implementationsarv är också en konstruktion som ofta missbrukas, vilket leder till kod som blir - svårbegriplig - oflexibel - svår att underhålla. 2 När skall man använda implementationsarv? Motiveringar för att använda implementationsarv: Återanvändning av kod Klass B kan utnyttja (data och metoder) som finns i klass A. Is-a relation Varje objekt av klassen B är också ett objekt av klassen A. Vilket betyder att mängden av alla objekt av klassen B är en delmängd av alla objekt i klassen A. ( En bil är ett fordon ) Det publika gränssnittet Det publika gränssnittet för klass B inkluderar det publika gränssnittet för klass A. Polymorfism Det finns ett behov av att kunna byta ut basklassen mot underklasser, dvs kunna tilldela ett objekt av klassen B till en variabel som deklareras av Implementationsarv för återanvändning av kod En av de verkliga fördelarna med implementationssarv är återanvändning av kod. Men är återanvändning av kod i sig en tillräcklig anledning att använda implementationsarv? Betrakta nedanstående UML-diagram: Dog -name: String -birthdate: Date +getname(): String +getbirthdate(): Date Möjligheten att ärva kod som annars skulle behöva dupliceras är en användbar egenskap hos objektorienterade språk, och därför skall man alltid överväga möjligheten att använda implementationsarv. Men enbart återanvändning av kod rättfärdigar inte implementationsarv. +getemployer(): Company klassen A. 3 4 Person -employer: Company En person är ingen hund!!

Liskov Substitution Principle (LSP) Metoden setsize(int width, int height) i klassen Rectangle har beteendet att ändra storleken på höjden oberoende av storleken på bredden. Metoden setsize(int width, int height) i klassen Square kan omöjligt ha detta beteende och fortfarande ha kvar egenskapen att vara en kvadrat. Från LSP följer således att en kvadrat INTE är en rektangel och att klassen Square därför inte skall implementeras som en subklass till klassen Rectangle. Har då matematikerna fel som säger att en kvadrat ÄR en rektangel? Nej, matematiskt betraktas alla geometriska figurer som icke-muterbara, d.v.s. när man matematiskt ändrar storleken på en rektangel skapas en helt ny rektangel. Våra klasser Rectangle och Square är muterbara, så vad LSP egentligen säger är att en muterbar kvadrat INTE är en muterbar rektangel. 13 is-a -relation och gemensamt gränssnitt Ett klassiskt exempel för att introducera begreppet arv är klasserna Person och Student. Uppenbarligen gäller att en student är en person. Ett objekt av klassen Student har alla egenskaper och alla beteenden som ett objekt av klassen Person har, såsom namn, födelsedag och adress. Klassen Student har dessutom ytterligare egenskaper såsom utbildningsnivå, linje, inskrivningsår och avklarade poäng. Man kan alltså här argumentera för att klassen Student skall vara en subklass till klassen Person. Men är detta en bra lösning? Person -name -address -birthday Student -grads -StudyProgramme -year -points 16

is-a -relation och gemensamt gränssnitt Anta att klasserna Person och Student skall användas i ett system för att lagra uppgifter om studenter på ett universitet. Antag också att man i samma system vill lagra uppgifter om de anställda på universitetet. Således behövs ytterligare en klass Employee. Av samma skäl som gällde för en student kan man argumentera för att Employee skall vara en subklass till klassen Person. Student -grades Person -name -address -birthday Employee -salary is-a -relation och gemensamt gränssnitt Vad händer om en student blir klar med sin examen och får en anställning på universitetet eller om en student under sin studietid får en deltidsanställning som övningsledare? Personen kommer att vara representerad av två objekt, ett Student-objekt och ett Employee-objekt. Det gemensamma datat som finns i Personklassen dupliceras! Ändras denna data måste detta åtgärdas i båda objekten, annars leder det till osynkroniserade data! :Student name = "Sven Stare" address = "Storgatan 19" birthday ="24 december" grades = {master, phd} :Employee name = "Sven Stare" address = "Storgatan 19" birthday ="24 december" salary = 345678 18 19 Delegering som alternativ till implementationsarv Delegering som alternativ till implementationsarv En bättre lösning än implementationsarv är i detta fall att se student och anställd som en roll som en person spelar. En sådan roll är ofta temporär, en person är inte alltid student eller anställd. På grund av den temporära karaktären hos rollerna (i vårt fall student och anställd) och den mera permanenta karaktären hos personen, är det inte lämpligt att låta klasserna Student och Employee vara subklasser till klassen Person. I vårt exempel innebär delegering att vi får exakt ett objekt av klassen Person för varje verklig person, som är oberoende av alla olika roller som spelas av denna person. En bättre design är att använda delegering och låta klasserna Student och Employee ha ett objekt av klassen Person, till vilket de refererar. Delegering innebär att ett objekt utåt erbjuder en viss tjänst, men internt överlåter ansvaret för att utföra tjänsten till ett annat objekt. Student -grades -person Employee -salary -person Person -name -address :Student person grades = {master, phd} :Employee person salary = 345678 :Person name = "John Doe" address = "Storgatan 19" birthday ="24 december" 20 21

Slutsatser Ett likadant gränssnitt är inte tillräckligt för ett elegant arvsförhållande, ett konsistent beteende är också nödvändigt. Subklasser skall lägga till nya beteenden, inte ändra redan befintliga beteenden. En klass A som är identisk med en klass B, förutom att den har extra restriktioner på sitt tillstånd, skall inte vara en subklass till B. Gör så många klasser som möjligt icke-muterbara. Överväg alltid om en subklass som inte tillför något eget unikt beteende verkligen behövs. Använd aldrig arv utan att beakta Liskov Substitution Principle. Subklasser som införs skall introducera äkta subtyper. 23 Implementationsarv ger stark koppling Vi skapar klassen CountChangeRectangle som en subklass till SimpleRectangle. Vi inför en instansvariabel nrofchange i CountChangeRectangle för att hålla reda på hur många gånger bredden av rektangeln förändras. Vidare överskuggar vi metoderna setwidth och setsize så att dessa metoder kontrollerar om bredden på rektangeln förändras och i så fall räknar upp instansvariabeln nrofchange. Metoderna setwidth och setsize i klassen CountChangeRectangle utökar alltså beteendet hos motsvarande metoder i klassen SimpleRectangle. SimpleRectangle -width: int -height: int +getwidth(): int +getheight(): int +setheight(int): void +setsize(int, int): void CountChangeRectangle -nrofchange: int +getwidthchanges(): int +setsize(int, int): void 25

Korrekt implementering För den givna implementationen av klassen SimpleRectangle, skall en korrekt implementation av CountChangeRectangle inte överskugga metoden setsize. SimpleRectangle -width: int -height: int +getwidth(): int +getheight(): int +setheight(int): void +setsize(int, int): void CountChangeRectangle -nrofchange: int +getwidthchanges(): int Överskygga endast metoden setwidth 31 Delegering är ett alternativ till implementationsarv För att kunna göra ett korrekt implementationsarv måste utvecklaren som skriver subklassen känna till implementationsdetaljer i superklassen. Ofta är delegering en bättre lösning än implementationsarv: ger en svagare koppling måste användas då implementationen är okänd. CountChangeRectangle -rect: SimpleRectangle -nrofchange: int +getwidth(): int +getheight(): int +setheight(int): void +setsize(int, int): void +getwidthchanges(): int SimpleRectangle -width: int -height: int +getwidth(): int +getheight(): int +setheight(int): void +setsize(int, int): void 33

Designa för framtida förändringar I en mer förutseende design hade klassen SimpleRectangle implementerat ett gränssnitt Rectangle. <<interface>> Rectangle +getwidth(): int +getheight(): int +setheight(int): void +setsize(int, int): void CountChangeRectangle SimpleRectangle -nrofchange: int -rect: SimpleRectangle +getwidthchanges(): int 35 Refaktorering: Exempel - rita polygon Vi skall i detta exempel utgå från ett program med mycket bristfällig design och stegvis förbättra designen (refactoring). Programet är ett enkelt ritprogram för att rita polygoner som antingen är kvadrater, retanglar eller trianglar, som i figuren nedan. Vi kommer endast att beakta den del i programmet som gör själva ritandet av polygonen. 37

Rita polygon: Design 5 Rita polygon Vi har åstadkommet en design som uppfyller Open-Closed principen. Den existerande koden behöver inte ändras när ny funktionalitet läggs till, t.ex. som att kunna rita ovaler, cirklar och hexagoner. Design 1: Ursprunglig design Design 2: DrawPolygons 1 String 1 Point * String * Point PolygonData * DrawPolygons Vi har gått från en rigid centraliserad design, där all data och funktionalitet var samlad på ett ställe, till en objektorienterad design där data och funktionalitet har distribuerats till ändamålsenliga klasser, och där arv och polymorfism används för att skapa en tydlig, flexibel och utbyggbar struktur. Design 3 & 4: Design 5: Slutlig design 1 String 1 Point Point 1 Polygon Polygon {abstract} * * DrawPolygons DrawPolygons Square Triangle Rectangle 50 51