TDP004 Objektorienterad Programmering Fö 6 Objektorientering forts.

Slides:



Advertisements
Liknande presentationer
Interface.  Interface är en datatyp och har alltså egen syntax och en hel del egna regler för vad arv från interface innebär.  Interface är renodlad.
Advertisements

Klasser och objekt.
Klassarv och inkapsling
OOP Objekt-orienterad programmering
Lennart Edblom, Frank Drewes, Inst. f. datavetenskap 1 Föreläsning 10: Objektorientering Objektorientering och abstrakta datatyper Dynamisk bindning.
ObjektOrienterad analys och design. SVP Vt2009 Föreläsning nr 2, måndag 8 april kl Diskussion (kurshemsida): Om designuppgiften Om projektuppgiften.
Arv.
Abstract & sealed.
Inkapsling.
Objektorienterad tänkande
Polymorfism.
Programmeringsteknik för K och Media
Föreläsning 13 Allt om tentan. Sistaminutenhjälp: På fredag 17 december kl 12 sitter Linda i kemi-fiket och svarar på frågor.
Föreläsning 6 Referenser Objekt som parametrar public/private Klassvariabler och klassmetoder.
1 Föreläsning 6 Klass Object, instans av klass public/private Klassvariabler och klassmetoder.
Alice in Action with Java
i olika programmeringsspråk
Sid period2CD5250 OOP med C++ Mats Medin MDH/IDT Objektbaserad programmering –Grundläggande om klasser och objekt – (Arv får vänta)  Iden med klasser.
Sid period2CD5250 OOP med C++ Mats Medin MDH/IDT Konstruktor Ser till att objektets data är korrekt initierade MinKlass::MinKlass(); MinKlass::MinKlass(int.
Föreläsning 13 Polymorfism, Paket och JAR-filer. Polymorfism Ordet härstammar från grekiskan Poly – många Morf – form Polymorf – många former Någonting.
Objektorienterad programmering i Java
Programmering i C# 3. Klasser.
PROCESSPROGRAMMERING
Jonny Karlsson INTRODUKTION TILL PROGRAMMERING Föreläsning 6 ( ) INNEHÅLL: -Mera om tabeller.
Pekare och speciell programstruktur i inbyggda system
Klasser och objekt Klasser, objekt och instansvariabler
Pointers. int a=5; int f(int b) { a--; b++; return b; } int main() { int a=3; printf("%d,",f(a)); printf("%d",a); return 0; }
int res2=Math.max(tal1,tal2);
Föreläsning 2 Kort Översikt Över Javaspråket. Källkodsformat Unicode används åäöμψζ tillåtna Inte alla miljöer klarar av det Källkod Bytekod Java VM för.
4. Arv och dynamisk bindning
Polymorfism.
Mer om arv - Polymorfism Kursbok: “Objects First with Java - A Practical Introduction using BlueJ”, David J. Barnes & Michael Kölling Fredric Ragnar
Programmering i C# 5. Structer.
Arv.
Programmeringsteknik för Media1 & K1
F. Drewes, Inst. f. datavetenskap1 Föreläsning 10: Objektorientering Objektorientering och abstrakta datatyper Dynamisk bindning Singel mot multipelt.
Jonny Karlsson INTRODUKTION TILL PROGRAMMERING Föreläsning 7 ( ) INNEHÅLL: -Klasser -Att definiera egna klasser -Klassvariabler -Klassmetoder.
Föreläsning 8 Arv och abstrakta klasser. Arv Definierar en klass utifrån en redan existerande klass Den nya klassen utökar den ärvda klassen ( extends.
Jonny Karlsson INTRODUKTION TILL PROGRAMMERING Föreläsning 8 ( ) INNEHÅLL:Klasser: -Konstruktorer -Klassvariabler -Instansmetoder -Privata.
Jonny Karlsson INTRODUKTION TILL PROGRAMMERING Föreläsning 7 ( ) INNEHÅLL: -Metoder -Lokala variabler -Mera om klasser: -Nyckelorden.
1 Föreläsning 6 Programmeringsteknik och Matlab 2D1312/2D1305 Metoder & parametrar Array API och klassen ArrayList.
Föreläsning 8 Programmeringsteknik och Matlab DD1312 Klassmetoder Egen modul, Self Metoderna: __str__, __lt__,… Meddelande Arv, Överlagring av metoder,
Föreläsning 9 Gränssnitt. Super Super kan användas till anrop av en omdefinierad metod Super kan användas till anrop av konstruktorer i superklassen Super.
Föreläsning 12 Om slutprovet. Repetition –deklaration av variabler –skapande av objekt (instansiering) –Vektorer och Vector-klassen –Klasser –Instans-/klassvariabler.
Föreläsning 4 Klasser Och Objekt.
1. Ett problem/uppgift.
Objektorienterad programmering i Java
Objektorienterad programmering
Föreläsning 2. Allmänt STL genererar varningar i Visual C++ –”#pragma warning (disable : 4786)”
1 Föreläsning 8 Mer om klasser och objektorientering.
Arv repetition Arv = Är relation Tillgänglighet public, protected och private. Överklass ös Direkt härledd underklass dhu: Class dhu : public ös{} Indirekt.
Föreläsning 17 Repetition. Källkodsformat Unicode används åäöμψζ tillåtna i namn på identifierare Inte alla miljöer klarar av det Källkod Bytekod Java.
Objekt, Klass och Instans Analys av systemet ger mer eller mindre detaljerade objekt Objekten sorteras och klass-diagram ritas upp där relationer reds.
OOP F5:1 Stefan Möller OOP Objekt-orienterad programmering Föreläsning 5 Klasser och objekt Skapa objekt - new Referenser Konstruktorer Inkapsling.
Föreläsning 5 Objekt Klasser Konstruktorer Metoder Minnesbilder av objekt.
Programmeringsteknik för K och Media
Föreläsning 5 Klasser och instanser
Föreläsning 7 Repetition Sammansatta datatyper –vektor (hakvektor, array) –matris.
OOP - teori1 OOP del II– Föreläsning 5 vecka 6. OOP - teori2 Klasser Substantiv i singularis stavat med stor bokstav till exempel Human Dog Account Circle.
1 Föreläsning 6 Repetition på metoder Referenser Objekt som parametrar public/private Klassvariabler och klassmetoder.
1 Föreläsning 4 Metoder & parametrar Array API och klassen ArrayList.
Malmö högskola Rolf Axelsson 2003/2004 DA7231, 4 poäng Referensvariabel Klass och konstruktorer Klass med set- och get-metoder Klass och fält Fler metoder.
OOP&M - teori1 OOPM del II– Föreläsning vecka Mer om ärvning.. Abstrakta klasser/metoder Gränssnitt/Interface klasser.
TDP004 Objektorienterad Programmering Fö 2 Objektorientering grunder.
TDP004 Objektorienterad Programmering Fö 7 Objektorienterad design, tips och råd.
1 Mer om metoder, variabler, klasser och objekt. Kursboken: - Kapitel 6 - Kapitel 8.
TDP004 Objektorienterad Programmering Fö 5 Minneshantering.
TDP004 Objektorienterad Programmering Fö 8 Sammanfattning
Objektorienterad programmering forts
Föreläsning 8: Exempel och problemlösning
Presentationens avskrift:

TDP004 Objektorienterad Programmering Fö 6 Objektorientering forts.

Introduktion Laboration på objektorientering. Viktiga objektorienterade begrepp: Superklass, subklass, arv. Abstrakta klasser. Virtuella funktioner. Polymorfi. Static. Laboration på objektorientering. Static är ett C++ nyckelord, inte ett generellt viktigt OO-begrepp.

Repetition från fö 2 I filen ExampleClass.h: class ExampleClass { public: // Publik åtkomstdeklaration ExampleClass(int defaultID); // Konstruktor ~ExampleClass(); // Destruktor bool SetID(int aID); // Medlemsfunktioner. const int GetID() const; float f(float a, float b, float c) const; private: // Privat åtkomstdeklaration int m_ID; // Klassvariabel. … }; // Observera ; För det mesta definieras funktionerna i .cc/.cpp-filen. Detta är ett exempel på en klass. Klassdeklaration med class klassnamn. Åtkomstdeklarationerna public och private har vi gått igenom tidigare. Vi ser konstruktorn och destruktorn som publika funktioner, samt 3 andra andra publika funktioner SetID, GetID och f. Det finns även en privat medlemsvariabel m_ID som är en int.

Repetition från fö 2, forts. Med åtkomstdeklarationerna public, protected och private reglerar man åtkomst till klassens data och funktioner för andra klasser. Den egna klassen har alltid obegränsad tillgång. Public – fritt tillgänglig för läs och skriv. Private – ingen tillgänglighet alls. Protected – tillgänglig enbart för subklasser. I class är allt private som default. I struct är allt public som default.

Arv Inom OO är arv ett viktigt begrepp: vi kan se arv som specialisering/förfining av en klass och dess funktioner. Klassen i toppen av arvshierarkin kallas superklass/basklass. Den klass som ärver av superklassen kallas subklass. Arvshierarkier ritas tex med UML. Nu kommer vi till arv vilket är ett av de allra viktigaste begreppen inom OO. Här har vi lite grundläggande terminologi. Arv handlar om att det finns en arvshierarki med en superklass överst, som sedan subklasserna ärver funktioner och medlemsvariabler från. Tanken är bland annat är funktioner och variabler som är gemensamma mellan olika klasser flyttas upp till en gemensam superklass. Detta ger också fördelen att man enbart behöver programmera funktionen en gång, och undviker därmed duplicering av kod vilket är en potentiell felkälla.

Arv, forts. En subklass är en specialisering av en superklass. Åtkomsten av en superklass funktioner och data varierar beroende på vilken sorts arv det är. I C++ finns det public, protected och private arv. Data/funktioner som är private i basklassen ärvs aldrig. Precis som det finns olika sorters åtkomst av funktioner och variabler så finns det olika sorters arv. Det man reglerar är vilket åtkomst superklassens funktioner får i subklassen. Värt att notera att en basklass privata funktioner aldrig kan ärvas till en subklass.

Olika sorters arv public: de ärvda funktionerna/datan behåller den åtkomst de hade i superklassen. protected: de ärvda funktionerna/datan blir protected i subklassen. private: de ärvda funktionerna/datan blir private i subklassen. Den ärvande klassen har alltså möjlighet att styra hur andra klasser ska komma åt de ärvda funktionerna. Man inte kan göra funktioner/data mera tillgängliga genom arv. Vi ser att den ärvande klassen till viss del kan påverka hur andra klasser kan få tillgång till de ärvda funktionerna och variablerna, men de kan aldrig bli mera tillgängliga än de var i basklassen. Detta för att behålla abstraktion och inkapsling.

Virtuell funktion Hittills har vi alltid implementerat alla funktioner i klassen. Vi kan även deklarera virtuella funktioner, dessa har nyckelordet virtual framför returvärdet: virtual double GetSpeed(); En virtuell funktion är ett kontrakt som alla subklasser måste uppfylla. En superklass som definierar en virtuell funktion kan själv implementera den (i C++, men inte i alla andra OO språk). Nyckelordet virtual skrivs enbart i .h-filen. Nu kommer vi till ytterligare ett viktigt koncept inom OO: virtuella funktioner. En virtuell funktion kan ses som ett kontrakt som måste uppfyllas: en funktion som måste heta en viss sak, ta vissa parametrar samt ha ett visst returvärde. Kompilatorn ser till att detta uppfylls. En virtuell funktion är på sätt och vis motsatsen till det vi pratade om att man flyttar implementationen av en funktion uppåt i arvshierarkin. Implementationen av en virtuell funktion görs normalt i subklassen.

Virtuella funktioner, forts. Vad är poängen med virtuella funktioner? Att kunna delegera utförandet av en viss beräkning till subklasserna och inte bry sig om hur de utför den. Detta koncept kallas polymorfism (mångformighet) och en sådan funktion kan definieras på olika sätt. Poängen med virtuella funktioner är att vi ska kunna ha ett interface som är en kontrakt att utföra något, och seadn kunna göra detta på olika sätt i olika subklasser. Vi delegerar alltså definitionen/implementationen till subklasserna och litar på att dessa uppfyller funktionen korrekt.

Rent virtuell funktion En rent virtuell funktion får inte definieras i den deklarerande klassen: virtual double GetSpeed() = 0; OBS! = 0 skrivs enbart i .h-filen. Detta gör det omöjligt att skapa en instans av klassen: det blir en abstrakt klass. Alla rent virtuella funktioner måste implementeras i subklasserna. En rent virtuell funktion kunde i C++ implementeras i basklassen, men det går även att göra funktioner som inte får implementeras i basklassen. Dessa kallas rent virtuella funktioner och markeras med = 0 efter namnet i .h-filen. Eftersom det är inte är tillåtet att implementera funktionen i basklassen blir det omöjligt att skapa en instans av den klassen: detta koncept kallas för en abstrakt klass. Likhet med interface i Java. Alla rent virtuella funktioner måste implementeras i alla subklasser, vilket kompilatorn ser till. Vi kan ta ett exempel med olika former som implementerar funktionen CalculateArea() på olika sätt.

Konstruktorer et.c. utelämnade. Shape virtual double Calculate Area() = 0; Abstrakt basklass Rectangle double CalculateArea() { return height * width; } Triangle double CalculateArea() { return (height * width) / 2.0; } Det finns en abstrakt basklass Shape som har en funktion som heter CalculateArea. Det finns även två subklasser, Rectange och Triangle. Dessa implementerar funktionern CalculateArea på olika sätt. Vad en abstrakt klass är ska vi strax gå igenom. Enkelt klassdiagram. Subklasserna definierar funktionen CalculateArea() på olika sätt. Konstruktorer et.c. utelämnade.

Polymorfism std::vector<Shape*> shapesVector; Shape* shape1 = new Triangle(…); Shape* shape2 = new Rectangle(…); shapesVector.push_back(shape1); shapesVector.push_back(shape2); shapesVector.push_back(…); Ex 1: for(unsigned int i = 0; i < shapesVector.size() ; ++i) { std::cout<< shapesVector[i]->CalculateArea() << ” ”; /* Anropar korrekt CalculateArea(), vi vet inte vilken implementation vid kompileringen. */ } Ex 2: shape1->CalculateArea(); //Anropar CalculateArea() i klassen Triangle. shape2->CalculateArea(); //Anropar CalculateArea() i klassen Rectangle. Fördelen med detta är att vi kan skapa olika Shapes och sedan anropa CalculateArea på dessa Shapes utan att i förväg veta vilken funktion som kommer att exekveras. I exemplet så gör vi just detta och sparar dem i en vector med Shape som element. Sedan itererar vi igenom denna vector och anropar CalculateArea för alla Shapes i vectorn. Korrekt implementation av CalculateArea kommer att anropas, men vi vet inte vilken implementation det är eftersom det kan finnas olika Shape i vectorn.

Polymorfism, forts. Vilken funktion som exekveras vid anrop till CalculateArea() avgörs vid exekveringen, sk dynamisk/sen bindning. En icke-virtuell funktion har sk statisk/tidig bindning: det bestäms vid kompilering vilken funktion som kommer att anropas.

Multipelt arv Det är fullt möjligt att ärva från flera klasser. Deklaration som vanligt. Man får se upp om flera basklasser i sin tur är subklasser till samma basklass, och implementerar virtuella funktioner olika. Detta problem löses på olika sätt i olika OO-språk.

virtual int f(int a, int b) = 0; C int f(int a, int b) { return (a * b); } B int f(int a, int b) { return (a + b) / 2; } D D* d = new D(); d->f(1, 3);? Vad händer då funktionen f anropas i klassen D? Detta utseende i arvshierarkin kallas för ”The diamond pattern”.

Virtuella destruktorer En virtuell destruktor i basklassen behövs vid arv, för att säkerställa att allt minne i basklassen lämnas tillbaka. En basklass bör definiera en virtuell destruktor även om basklassen inte har något att ta bort. En kompilatorgenererad destruktor är aldrig virtuell. Det är ingen nackdel att göra alla destruktorer virtuella.

Static En static medlems-/variabel-funktion finns bara i ett exemplar som är gemensam för klassen, den hör alltså inte till någon instans av klassen. Användbart när man vill ha någonting som det bara finns en av och som alla instanser kan använda. Ex på nästa slide: alla instanser av en klass ska ha ett unikt ID-nummer. C++ nyckelord static talar om att något, det vi deklarerar static, bara existerar i ett exemplar. Detta är gemensamt mellan alla instanser och kan användas av alla.

Static variabel I .h-filen I .cc-filen static int ourID; // Static variabel. int m_ID; // Vanlig medlemsvariabel. I .cc-filen /* En static variabel måste initieras utanför funktionerna. */ int classname::ourID = 1; // Men kan användas i alla klassens funktioner. classname:: classname() { m_ID = ourID; // Tilldela ett unikt ID. ourID++; }

Lokala static variabler Även lokala varibler kan vara static. Ex: Vi vill igen ge alla instanser ett unikt ID-nummer. classname:: classname() { static int ourID = 0; // Exekveras endast en gång. m_ID = ourID; // Tilldela ett unikt ID. ourID++; } Nackdelen jämfört med förra metoden är att vi inte har tillgång till ourID utanför konstruktorn, om vi t.ex. skulle vilja få reda på det nuvarande värdet på ourID. En lokal variabel som är static är lite speciell. Den finns också bara i ett exemplar som delas mellan de olika instanserna, och den håller sitt värde mellan anropen till funktionen, och kan alltså i en del applikationer användas för att spara ett tillstånd istället för en static medlemsvariabel.

Static funktioner Även funktioner kan vara static. En static funktion kan anropas även om det inte finns några instanser av klassen. Får endast använda statiska klassvariabler (lokala variabler som vanligt). Kan endast anropa andra funktioner som inte tar this-pekare som parameter (static-funktioner och konstruktor). I tidigare föreläsning pratade vi om att de flesta funktioner tar en osynlig extra parameter, this. Undantagen är konstruktorer och static variabler. Detta gör dem speciella eftersom det går att anropa dem även om det inte finns någon this, dvs det går att anropa dem utan att det finns någon instans av klassen. Men det för också med sig att de enbart kan anropa andra funktioner som även de är static, samt enbart använda medlemsvariabler som är static. Orsaken till detta är att annars skulle en static variabel kunna ändra på ett objekts tillstånd, utan att det finns någon instans av objektet.

Copy constructor och tilldelningsoperator Copy constructor skapar en kopia av instansen. Tilldelningsoperator tilldelar endast. Kompilatorns copy constructor är public som default. Utseende enligt: klassnamn(klassnamn&) Ex: ExampleClass(const ExampleClass&); Skapas av kompilatorn om inte programmeraren gör det.

Copy constructor och tilldelningsoperator, forts. Tilldelningsoperator för att tilldela en instans. Utseende enligt: klassnamn& operator=(const klassnamn&) Ex: ExampleClass& operator=(const ExampleClass&); Defaultbeteende för den automatgenererade tilldelningsoperatorn är bitvis kopiering av data. Ett exempel på bitvis kopiering av data: If medlemsvariabeln är en pekare kopieras pekarens adress istället för pekarens innehåll.

Exempel där tilldelningsoperator behövs class Athlete { public: Athlete(const char* value) ~Athlete(); private: char* name; };

Exempel, implementation Athlete::Athlete(const char* value) { if(NULL != value) name = new char[strlen(value) +1]; strcpy(name, value); } else name = new char[1]; name= ’\0’; Athlete::~Athlete() delete [] name;

Exempel, användning Athlete* A = new Athlete(”Sanna Kallur”); Athlete* B = new Athlete(”Henrik Larsson”); Henrik Larsson\0 Sanna Kallur\0 B A name name

Exempel, tilldelning B=A; Vad hände? Henrik Larsson\0 Sanna Kallur\0 A name Eftersom det inte finns någon tilldelningsoperator, skapar C++ en som kopierar datan bitvis. name

Exempel, forts. Problem Lösning Minnesläcka. Ursprungligt minne för variabeln ”name” för instans B (”Henrik Larsson\0”) kommer inte att tas bort. Antag att destruktorn för instans A körs och name tas bort. Vad händer när konstruktorn för instans B körs? Lösning Implementera tilldelningsoperator vilken korrekt kopierar name.

Exempel där copy constructor behövs Antag att ingen copy constructor finns. void doNothing(Athlete a) { //Nothing is performed. } Athlete C(”Mats Sundin”); doNothing(C); Vad händer med C när doNothing returnerar? doNothing tar ju hela objektet, ingen pekare eller referens. Destruktorn körs när doNothing returnerar. Generellt kan man säga att när man allokerar minne i konstruktorn behöver man cc och = En nödlösning är att deklarera cc/= private men implementera dem inte. Kompilatorn kan inte skapa egna och de kan inte användas av något annat än klassen själv.

Sammanfattning Arv, superklass och subklass. Public, protected och private arv. Multipelt arv. (Rent) virtuella funktioner, abstrakta klasser. Polymorfi. Dynamisk och statisk bindning. Nyckelordet static för funktioner och variabler.