Arv och klassbibliotek Johan L Larsson Uppsala Universitet/KTH November 1999 jola@csd.uu.se 1 Klasser och objekt Car instantiates particularcar jola@csd.uu.se 2
Introduktion till arv Problem med modifikation av slutna moduler: man vill helst undvika att göra ändringar. Det är naturligt att organisera många problem hierarkiskt, dvs i olika nivåer. Arv är delta-change, dvs ändring genom att ange skillnad mellan klasser. En subklass ärver från en superklass och får då allt som superklassen har, plus mer! jola@csd.uu.se 3 Exempel Vehicle Land Vehicle Water Vehicle Air Vehicle Car Truck Boat Submarine Airplane Rocket Antag att Vehicle har: Attributet fspeed Metoden accelerate() Då har alla klasserna åtminstone: Attributet fspeed Samma metod accelerate() men dom kan ha mer! jola@csd.uu.se 4
Olika typer av arv Enkelt arv ( single inheritance ) Klasserna bildar hierarkier där varje klass har endast en superklass. Multipelt arv ( multiple inheritance ) Klasserna bildar komplexa grafer där en klass kan ärva från flera andra klasser. Problem med entydighet, komplicerade beroenden, etc, gör att Java saknar detta. Interface- arv (som i Java) Ren subtypning (utan att kod ärvs) jola@csd.uu.se 5 Typer - 1 En typ är en mängd värden och en mängd operatoner på dessa värden. Typer låter oss på ett säkert sätt para ihop operationer med de värden där de tillåts. Typfel kan antingen Message hanteras av kompilatorn Object eller under körningen. = statisk ( strong ) respektive ( weak ) dynamisk typning Type error (message not found) jola@csd.uu.se 6
Typer - 2 Typer ger oss säkrare programmering. Statisk eller dynamisk typning? Industrin föredrar traditionellt statisk typning som i Ada, Pascal, C, C++, Java, Eiffel m fl: + Undviker körningsfel redan vid kompilering + Gör program mer tillförlitliga i potentiellt farliga situationer, t ex i ett flygplan. + Snabbare körning (typkontroll är kostsamt) Mindre flexibel programvara (jfr Smalltalk) jola@csd.uu.se 7 Konstruktion av (sub-) typer Viktig egenskap hos OO PL: användare kan bygga nya typer från gamla: Genom att köpa, dvs låta klasser innehålla attribut av andra klasser precis som strukturer i Pascal eller C (record/struct). Genom arv. Nya subtyper Vehicle ärver från gamla typer, eventuellt med tillägg (attribut, metoder). Car has-a is-a Wheel jola@csd.uu.se 8
Dynamisk bindning Bidning: ett väre måste ges en typ innan den kan användas. På samma sätt måste objekt ges en klass innan de mottar meddelanden, etc. Dynamisk bindning = ett objekt ges en klass vid tilldelning, ej vid deklaration. jola@csd.uu.se 9 Principle of Substitutability Instanser av en subklass innehåller alla attribut som finns i en superklass. Instanser måste kopiera superklassens alla metoder. Därför kan en subklass härma en superklass så att vi kan behandla dem lika. If we have two classes A and B, such that class B is a subclass of A, it should be possible to substitute instances of clss B for instances of class A in any situation with no observable effect. [Budd96] jola@csd.uu.se 10
Specialisering med arv En subklass kan vara en specialisering av superklasen. T ex är bil en specialisering av fordon. Window kan specialiseras till TextWindow Raffinering ( refinement ) av superklassen Subklassen blir också en subtyp Subklassen kan bytas ut mot superklassen närsomhelst. jola@csd.uu.se 11 Arv som specifikation Arv kan garantera att en subklass uppfyller en specifikation (gränssnitt, etc). Till skillnad från specialisering är superklassen inte komplett utan måste fyllas med funktion, helt eller devis. Mer specifik Mer generell Abstrakta klasser är klasser som inte kan användas - dom saknar metoder etc jola@csd.uu.se 12
Arv som konstruktion (är-del-av) En klass kan ärva från en eller flera klassar för att få all sin funktionalitet. Man plockar då in beteende från klasser av intresse och använder arv för detta. Bryter ofta principle of substitutability : subklasser blir inte alltid subtyper. Privat arv löser problem med arv för konstruktion. jola@csd.uu.se 13 Arv som generalisering Motsats till specialisering Exempel: ColoredWindow ärver från Window och blir ett mer generaliserat fönster. Det har ju färg. Bygger ofta på tillägg av attribut, t ex färg i exemplet. Bör undvikas: vänd istället typhierarkin. jola@csd.uu.se 14
Arv för utökning Utökning ( extension ) = expandera med funktionalitet i superklassen som är helt nytt (dvs ej raffinering av gamla funktioner) StringSet som kan tänkas ärva Set tillhandahåller säkert flera helt nya metoder. De är utökningar av superklassen. Finns någon fördel med att lämna gammal funktionalitet som den är? jola@csd.uu.se 15 Arv för kombination Man vill ibland kombinera funktionalitet ifrån flera klasser i en enda klass (multipelarv) Detta kan ge problem om funktionalitet kolliderar (t ex metoder har samma namn) jola@csd.uu.se 16
Arv för begränsning Om en klass ärver från en superklass med funktionalitet som ej behövs kan subklassen begränsas Man kan då överskriva med tomma metoder och eventuellt göra anrop till programfel. Bör aldrig användas! (Varför?) jola@csd.uu.se 17 En liten slutsats Arv kan användas på ett dåligt sätt om vi inte tänker oss för! jola@csd.uu.se 18
Överskrivning Att ersätta en metod med en ny metod genom arv kallas överskrivning En form av polymorfism som baserar sig på dynamisk bindning Vi använder virtual (Java, C++, Object- Pascal) för att markera vilka metoder som inte binds fast då vi deklarerar klasser Virtuella metoder binder meddelanden till objekts klasser under körningen jola@csd.uu.se 19 Kovarians Överskrivning av en metod med en parameter som blir en subklass, dvs parametern följer efter arvsriktningen. Driver Truck- Driver Car Vehicle Truck setdriver (Driver d); Mer generell setdriver (TruckDriver d); Kan ge problem med typkompatibilitet (Truck.setDriver accepterar bara en delmängd av typerna) jola@csd.uu.se 20
Kontravarians Överskrivning av en metod där parametern blir en superklass. Driver Vehicle setdriver (TruckDriver d); Mer specifik Truck- Driver Car Truck setdriver (Truck d); jola@csd.uu.se 21 Avancerad överskrivning Vi kan ställa krav på överskrivningen: En viss grupp av metoder måste överskrivas samtidigt. Inramade metoder: tillåt överskrivning med before method eller after method (CLOS) Kovarians och kontravarians. jola@csd.uu.se 22
Multipelarv - 1 Diamond-inheritance + om man tänker sig arv som kombination av beteenden i superklasser blir multipelarv en naturlig utökning. Ex. C++ och Eiffel. + Modellering blir nu annorlunda - vad som var svart med enkelt arv blir nu lätt. Number Integer Magnitude jola@csd.uu.se 23 Multipelarv - 2 Tvetydighet med namn: Byt namn utan att ändra metod Definiera om metoder/attribut Delad superklass: Dubbla kopior av attribut etc. Virtuella superklasser som i C++ Stream InStream OutStream InOutStream jola@csd.uu.se 24
Några fler problem med arv Hur kan vi ändra klasser mitt i hierarkier, eller är vi begränsade till utkanten av hierarkierna? Är det lätt att läsa långa klasshierarkier där ett visst objekts beteende kan härstamma från väldigt många klasser? Jojo-effekt. Kan vi använda en enskild klass i ett annat program eller måste vi flytta över en hel hierarki av klasser? Blir verkligen subklass en subtyp? Kontrakt? jola@csd.uu.se 25 Alternativ till arv Enkelt arv ( single inheritance ) Komplettera med nästade klasser Komplettera med interface-arv Multipelt arv Ger stora möjligheter men ibland problem Inget (implementations-) arv: Subtyper (interface-arv) Has-a relationer (klasser som attribut) jola@csd.uu.se 26
Klassbibliotek och hierarkier Språk såsom Java och Eiffel tillhandahåller ett stort antal klasser i ett så kallat klassbibliotek. Klassbibliotek baserar sig på arvsrelationer. Klassbibliotek ska inte ändras. Vi använder arv för att överskriva beteende. Klassbibliotek kan använda abstrakta klasser som vi måste utöka beroende på vad vi exakt vill använda biblioteket till. jola@csd.uu.se 27 Klassbiblioteket i Eiffel Array List List Node Fixed List Linked List Bi-List Node Bi-Linked List Tree Node jola@csd.uu.se 28
Att lära av andra = reuse Återanvändning! Genom att använda arv kan vi använda klassbibliotek utan att göra modifikationer. Vi slipper förstå detaljer om klasser och behöver bara första ett fåtal metoder även om en mängd metoder används. jola@csd.uu.se 29 Att bygga klassbibliotek Det är svårt att bygga bra klassbibliotek! Klasserna måste vara tillräckligt öppna för utökningar och anpassningar Klasserna får inte vara inlåsta i arv (vi behöver has-a relationer för att det ska bli flexibelt) Vi måste välja rätt arvsrelationer: t ex vad ska egentligen finnas i den gemensamma superklassen för alla datastrukturer Vi måste förstå hur biblioteket ska användas! jola@csd.uu.se 30
Ett steg mot frameworks Objekt-orienteade frameworks är ett aktuellt forskningsområde! Ett framework är ett bibliotek av klasser som vävts mycket tätt samman. De bildar en abstrakt applikation med extremt mycket gömda detaljer. Frameworks är svåra att konstruera, svåra att lära sig - men mycket kraftfulla för återanvändning! jola@csd.uu.se 31 Nästade klasser Klasser kan vara medlemmar i andra klasser i t ex Java och C++: class EnclosingClass {... class NestedClass { } } Nästade klasser löser problem med encapsulation: den nästade klassen kommer åt den yttre klassens medlemmar, även de som är deklarerade som private. Underlättar organisering av kod. jola@csd.uu.se 32
Motivation till nästade klasser // An example with cluttered but valid code public class MyClass implements MouseListener {... someobject.addmouselistener(this);... /* Empty method definitions. */ public void mousepressed(mouseevent e) { } public void mousereleased(mouseevent e) { } public void mouseentered(mouseevent e) { } public void mouseexited(mouseevent e) { } public void mouseclicked(mouseevent e) { } } Svårt att utöka och mycket kod att skriva. jola@csd.uu.se 33 Vi vill ha en inre klass MouseAdapter som vi senare kan utöka. // An example of using an inner class public class MyClass extends Applet {... someobject.addmouselistener(new MyAdapter());... } class MyAdapter extends MouseAdapter { } Nästade klasser i Java public void mouseclicked(mouseevent e) { } Annat exempel: iterator som inre klass till datastrukturer jola@csd.uu.se 34
Polymorfism: en överblick Polymorphism Ad hoc Universal Coercion Overloading Inclusion Sub-type Parametric Code Objects jola@csd.uu.se 35 Några uppgifter Uppgift 1: ge konkreta exempel på när det är bättre med arv än komposition (has-a)! Uppgift 2: ge konkreta exempel på när det är bättre med komposition (has-a) än arv! Uppgift 3: ge motivering till varför en subklass inte behöver vara en subtyp (med exempel)! jola@csd.uu.se 36