Objektorientering - Arv och polymorfi

Relevanta dokument
TDDC76 - Programmering och Datastrukturer

TDIU20 - Objektorienterad programmering i c++ - föreläsning 6

TDDC76 - Programmering och Datastrukturer

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

TDDC76 Programmering och datastrukturer

Programmering i C++ EDA623 Arv. EDA623 (Föreläsning 6) HT / 42

Innehåll. 1 Kort om dynamisk polymorfism. 2 Arv i C++ 3 Multipelt arv. 4 Något om statisk polymorfism. class Container {

Innehåll. Konstruktorer vid arv Regler för basklassens konstruktor. Konstruktorer vid arv. Konstruktorer vid arv. Konstruktorer vid arv

Innehåll. Pekaren this Självreferens. Klasser Resurshantering, representation. Överlagring av operatorer. Överlagring av operatorer

TDIU20 - Objektorienterad programmering i c++ - föreläsning 4

TDDC76 - Programmering och Datastrukturer

Arv. Objektorienterad och komponentbaserad programmering

TDIU01 Programmering i C++

Innehåll. Typomvandlingar (casting) Implicita Typomvandlingar. Typomvandlingar (casting) Implicita Typomvandlingar

Introduktion till arv

Del2 Klasser, medlemmar och arv Ämnesområden denna föreläsning:

C++ Objektorientering - Klasser. Eric Elfving Institutionen för datavetenskap

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

Operatoröverlagring. endast operatorsymboler definierade i C++ kan överlagras = += -= *= /= %= ^= &= = <<= >>= < > <= >= ==!= && > ->*, [ ] ( )

Dynamisk bindning och polymorfism

TDDC76 - Programmering och Datastrukturer

C++ Objektorientering - Klasser. Eric Elfving

Kapitel 6 - Undantag

Introduktion. Klasser. TDP004 Objektorienterad Programmering Fö 2 Objektorientering grunder

Innehåll. Pekare Exempel

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

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

Del3 Klassanvändning, operatorer och pekare Ämnesområden denna föreläsning:

Innehåll. Pekare Exempel

Programsystem konstruktion med C++ (2D1387) Innehåll. övning 2 klasser och arv

Programmering i C++ EDA623 Objektorienterad programutveckling. EDA623 (Föreläsning 5) HT / 33

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

Kapitel 3. Synlighet. Kapitel 3 - Klassanvändning, operatorer och pekare. Synlighet

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

Innehåll. Resurshantering. Resource handles. Minnesallokering. Minnesallokering Exempel: allokering på stacken. 6. Resurshantering

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

Klasser. Kapitel 2. Kapitel 2 - Klasser, medlemmar och arv. Klasser. Klasser Medlemmar Arv

TENTAMEN CD5250. Objektorienterad programutveckling med C++, 5p. Datum: , Tid: 14:00-19:00

Klasshierarkier - repetition

Skapa, kopiera och destruera klassobjekt

Tentamen i TDP004 Objektorienterad Programmering Lösningsförslag

Innehåll. Resource handles. Resurshantering. Minnesallokering. Minnesallokering Exempel: allokering på stacken. 7. Resurshantering, Felhantering

5 Arv och dynamisk bindning FIGUR

TDIU20 - Objektorienterad programmering i c++ - föreläsning 3

Synlighet. Namespace Scope-operatorn Klasser Vänner

Lektionsuppgifter. TDDI14 Objektorienterad programmering. Lektionsplanering Lektion Lektion Lektion

Trädtraversering. Binärt träd. Trädtraversering djupet-först. Trädtraversering bredden-först

Tillämpad programmering

Tentamen EDAF30 Programmering i C++

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

Programsystemkonstruktion med C++

KLASSER. Inkapsling Abstrakt datatyp Public och private. Klassmedlemmar Datamedlemmar Exempel Funktionsmedlemmar

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

Generiska konstruktioner. Kursbokens kapitel 13

Programmering i C++ EDAF30 Dynamiska datastrukturer. EDAF30 (Föreläsning 11) HT / 34

Programsystemkonstruktion med C++: Övning 2. Karl Palmskog september 2010

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

1 Namnkontroll (NameControl)

Objektorienterade programmeringsspråk. Objektorienterade språk. Den objekt-orienterade modellen. Jämför med icke-oo

Objektorienterad Programkonstruktion. Föreläsning 4 8 nov 2016

Arv bakgrund (kap. 9)

DAT043 - Föreläsning 7

Högskolan Dalarna sid 1 av 5 Data-avdelningen Hans-Edy Mårtensson

Polymorfi. Objektorienterad och komponentbaserad programmering

Innehåll. Typomvandlingar (casting) Implicita Typomvandlingar. Typomvandlingar (type casts) Explicita, namngivna typomvandlingar (C++-11)

Programmering i C++ EDA623 Mallar. EDA623 (Föreläsning 12) HT / 29

Objektorienterad Programmering (TDDC77)

Classes och Interfaces, Objects och References, Initialization

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

Vad är en klass? Övning 2. Konstruktorer. ffl copy-konstruktorn tar en instans av klassen som. ffl default-konstruktorn tar inga argument och kan

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

Innehåll. Introduktion till objektorientering. OOP (objektorienterad programmering) Objekt, instanser, klasser

TDIU01 - Programmering i C++, grundkurs

Högskolan Dalarna sid 1 av 5 Data-sektionen Hans-Edy Mårtensson

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

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

Objektorienterad Programmering (TDDC77)

Föreläsning 3: Abstrakta datastrukturer, kö, stack, lista

TDIU01 - Programmering i C++, grundkurs

Arv Murach s: kap 14

Övriga byggstenar. Övriga byggstenar. Några tips under programutveckling. Beroenden Pekare till funktioner Typkonvertering

Innehåll. Användardefinierade typer. Användardefinierade typer Kategorier. Konstruktorer. Konstruktorer Två sätt att skriva initiering av medlemmar

Innehåll. 1 Typdeklarationer och typomvandling 2 Resurshantering. 3 Objektorientering, kort repetition. 4 Klasser

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

TDDC76 PoD OH Föreläsning C Härledda klasser

Konstruktion av klasser med klasser

Klasser. Det är egentligen nu som kursen i programmeringsteknik börjar..., s k objektorienterad programmering.

Arv och polymorfi. Lite terminologi; Basklass eller superklass: En klass som fungerar som bas för vårt arv. Vi skapar nya klasser utifrån den.

TDIU01 - Programmering i C++, grundkurs

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

Kopiering av objekt i Java

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

Idag. Javas datatyper, arrayer, referenssemantik. Arv, polymorfi, typregler, typkonvertering. Tänker inte säga nåt om det som är likadant som i C.

Innehåll. Exceptionella händelser (exceptions, undantag ) Felhantering Tre nivåer av felhantering: Nivå 2: exceptions (eller returvärde)

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

Innehåll. 1 Funktionsmalllar. 2 Klassmallar. struct Name { string s; //... }; const Name & minimum ( const Name & a, const Name & b) { if(a.s < b.

Föreläsningsmaterial (Arv) Skrivet av Andreas Lund

OOP Objekt-orienterad programmering

Programmering med Java. Grunderna. Programspråket Java. Programmering med Java. Källkodsexempel. Java API-exempel In- och utmatning.

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

Transkript:

Objektorientering - Arv och polymorfi För kurserna TDDC76 och TDIU20 Klas Arvidsson Institutionen för datavetenskap

1 / 38 UML UML är ett grafiskt språk som (bland mycket annat) används för att beskriva relationen mellan klasser i objektorienterade system. Vi tar upp fyra olika relationer och hur de ritas: Arv: En Person är en Människa med allt det innebär. Komposition: En Person har en Kropp. Aggregation: En Person kan ha Klädesplagg. Association: En Person kan använda Hyrbil.

2 / 38 CRC-kort (analysmetod) Vid objektorinterad analys kan vi använda CRC-kort för att komma fram till de klasser som behövs, och varje klass ansvar och samarbetspartners. Använd t.ex. postit-lappar och skriv på varje upp: Class (klassens namn) Resposibility (klassens ansvarsområde) Collaborators (samarbetspartners till klassen, hjälpklasser)

3 / 38 UML relationer som figur/graf (analysresultat) Human Body Person Cloth. RentalCar

4 / 38 UML klasser i större detalj När de klasser vi behöver är identifierade kan vi specificera dem i större detalj. Datamedlemmar, medlemsfunktioner och dess åtkomst specificeras: + anger public - anger private # anger protected : typ anger datatyp/returvärde

5 / 38 UML relationer som figur/graf (designresultat) Human # iq : int Cloth vector - name : string Person + put_on(cloth const& c) : bool + drive(rentalcar const& c) : bool RentalCar - top_speed : int Body. + groom() : void + ignition(bool on) : void + accelerate(int delta) : void + turn(double angle) : void

6 / 38 UML relationer C++-kod class Person : public Human // inheritance, is public: Person() : Human(), body, clothing void put_on(cloth const&); void drive(rentalcar&); // association, knows about private: Body body; vector <Cloth > clothing; ; // composition, always part of // aggregation, can come and go

7 / 38 Inre klasser, publik inre klass Inre klasser tillåter privat composition, aggregation eller association Endast huvudklassen kan skapa MSDC_Iterator-objekt men MSDC_Iterator är synlig för alla att använda. class My_Superior_Data_Container private: class MSDC_Element; // forward declaration (why?) public: class MSDC_Iterator // inner public class private: friend class My_Superior_Data_Container; MSDC_Iterator(MSDC_Element*); ; MSDC_Iterator begin(); MSDC_Iterator end();

8 / 38 Inre klasser, privat inre klass Inre klasser tillåter privat composition, aggregation eller association Endast huvudklassen kan skapa och använda MSDC_Element. private: class MSDC_Element // inner private class // declarations ; MSDC_Element* my_superior_start; ;

9 / 38 Inre klasser, (medlems)funktionsdefinition Som vanligt måste medlemskapet specificeras noga! My_Superior_Data_Container::MSDC_Iterator:: // member specification MSDC_Iterator(MSDC_Element*) // member initialization list // constructor implementation My_Superior_Data_Container::MSDC_Iterator // function return type My_Superior_Data_Container:: // member specification begin() return MSDC_Iteratormy_superior_start;

10 / 38 En (annan) Person vi kommer att utgå från class Person public: Person(string n, string p) : namen, phonep string get_phone() const return phone; void print_info(ostream& os) const; private: string name; string phone; ;

11 / 38 Arv till Employee Vi vill nu skapa en anställd. En anställd är en person med lön och arbetstelefon. Hur skapar vi den klassen när vi redan har en person? Vi kan kopiera och klistra till helt ny klass Employee. Det innebär att allt framtida arbete med Person-klassen manuellt måste dupliceras till Employee. Vi kan låta en ny Employee-klass innehålla en Person som datamedlem. Det innebär att vi måste skapa nya funktioner i Employee för att komma åt allt i Person.

12 / 38 Arv till Employee Vi kan använda arv för att berätta för kompilatorn att en ny klass Employee automatiskt är allt som en Person är. Person blir basklass och Employee blir härledd klass (alternativt subklass): class Employee : public Person public: Employee(string n, string p, string w, int s) : Personn,p, work_phonew, salarys string get_phone() const; string get_home_phone() const; string get_work_phone() const return work_phone; int salary() const; private: string work_phone; int salary; ;

13 / 38 Anrop av basklass från subklass En härledd klass har direkt alla datamedlemmar och medlemsfunktioner som finns i basklassen. Det går även att explicit ange att basklassens medlem ska användas. Men inte ens en härledd klass har tillgång till basklassens privata medlemmar! string Employee::get_phone() const return Person::get_phone() + ", " + work_phone; string Employee::get_home_phone() const return phone; // Compilation error, private to Person!

14 / 38 Åtkomst av basklass från subklass Vi kan i basklassen ge härledda klasser tillgång till medlemmar med nyckelordet protected! class Person public:... private: // endast för klassen själv string name; protected: // endast för klassen själv och härledda klasser string phone; ;

15 / 38 Publikt vs privat arv Har du tänkt på varför public behövs vid arv? class Employee : public Person Vad händer om vi skriver något annat? public: medlemmar i basklassen behåller deklarerat skydd protected: public medlemmar i basklassen blir protected i härledd klass private: alla medlemmar i basklassen blir private i härledd klass Notera att privata medlemmar i basklassen aldrig är åtkomliga i subklassen. Lämnar du tomt väljs privat arv som standard.

16 / 38 Statisk bindning I C++ används statisk bindning om inget annat anges. Det innebär att datatypen som anges i programkoden avgör vilken funktion som anropas. Person kim"kim", "2146"; Employee sam"sam", "2490", "1234", 40000; Person& refsam; cout << kim.get_phone() << endl; // 2146 cout << sam.get_phone() << endl; // 2490, 1234 cout << sam.get_work_phone() << endl; // 1234 cout << ref.get_phone() << endl; // 2490 cout << ref.get_work_phone() << endl; // Compilation error! sam.print_info(cout); // Sams uppgifter skrivs ut på cout kim.print_info(cout); // Kims uppgifter skrivs ut på cout

17 / 38 Import eller borttagning av basklassmetoder Det går att välja och vraka vilka medlemsfunktioner från basklasserna som ska finnas i den härledda klassen. // Tillfällig vikarie class Substitute : public Employee public: using Employee::Employee; // Ger konstruktor motsvarande Employee using Person::get_phone(); // Väljer versionen i Person string get_work_phone() const = delete; ; Substitute s"toni", "4711", "", 60000; s.get_phone(); // The version in Person s.get_work_phone(); // Compilation error!

18 / 38 En härledd klass har flera datatyper! En härledd klass är både sin egen datatyp och basklassens datatyp! En vikarie kan alltså användas som Person, Employee och Substitute. Vi bör dock tänka oss för vid tilldelningar! Person p"p", "1"; Substitute s"s", "2", "3", 0; p = s; // Ok, men ger slicing Employee& e = s; // Ok Person* pp = &s; // Ok Substitute v = e; // Compilation error!

19 / 38 En härledd klass har flera datatyper! En referens av typ T kan hänvisa till en typ härledd från T. En referens av typ T kan inte hänvisa till en bastyp av T. Ovanstående gäller även pekare! Ett objekt av typ T rymmer aldrig en härledd typ och kan inte lagra enbart en bastyp.

20 / 38 Exempel: std::ostream& std::ostream är basklassen för alla utströmmar! Genom använda en std::ostream& som parameter kan funktioner ta valfri härledd utströmtyp! void print_hello(ostream& os) os << "Hej" << endl; ofstream ofs"hello.txt"; ostringstream oss; print_hello(ofs); // print to file print_hello(oss); // print to stringstream print_hello(cout); // print to standard output print_hello(cerr); // print to standard error

21 / 38 Exempel: std::exception& std::exception är basklassen för alla standardundantag! Genom att fånga en basklassreferens kommer vi att fånga även alla undantag härledda från den fångade basklasstypen! try // Kod som kastar undantag... catch( logic_error& e) // Fångar logic_error i första hand catch( exception& e ) // Fångar klasser härledda från exception i andra hand

22 / 38 Löneberäkning för olika kategori anställda Vi kan samla olika kategorier av anställda i en lista! Hur blir det om lönen ska beräknas olika? vector <Employee*> v; v.push_back(new Employee...); v.push_back(new Programmer...); v.push_back(new CEO...); v.push_back(new Consult...); for ( Employee const* e : v ) cout << e->salary() << endl;

23 / 38 Programmer class Programmer : public Employee public: Programmer(..., double e = 1.0) : Employee(...), expertisee int salary() const return salary * experise; private: double expertise; ;

24 / 38 Consultant class Consultant : public Employee public: Consultant(..., int p, int h) : Employee(...), hour_payp, hours_workedh int salary() const return salary + hour_pay * hours_worked; private: int hour_pay; int hours_worked; ;

25 / 38 CEO class CEO : public Employee public: CEO(..., int bonus = 1000000) Employee(...), bonusbonus int bonus() const return bonus; int salary() const return salary + bonus; private: int bonus; ;

26 / 38 Löneberäkning för olika kategori anställda Om inget annat anges får vi statisk bindning! Det är alltså Employee::salary() som anropas! vector <Employee*> v; v.push_back(new Employee...); v.push_back(new Programmer...); v.push_back(new CEO...); v.push_back(new Consult...); for ( Employee const* e : v ) cout << e->salary() << endl;

27 / 38 Dynamisk bindning (virtual, override, final) Basklassen måste med virtual ange om härledda klasser har en egen variant en funktion! Den härledda klassen ska med override ange att den ersätter basklassens variant, eller final. class Employee : public Person... virtual int salary() const;... protected: int salary; ; class CEO : public Employee... int salary() const override;... ;

28 / 38 Polymorfi När funktionen är virtual får vi dynamisk bindning (polymorfi)! Nu är det den salary() som finns i det objekt som pekas ut som anropas! vector <Employee*> v; v.push_back(new Employee...); v.push_back(new Programmer...); v.push_back(new CEO...); v.push_back(new Consult...); for ( Employee const* e : v ) cout << e->salary() << endl;

29 / 38 Bara pekare och referens kan ha dynamisk typ Vi får endast dynamisk bindning när: Vi från en basklasspekare anropar en virtual funktion, eller Vi från en basklassreferens anropar en virtual funktion!

30 / 38 Dynamisk typomvandling (pekare) När vi har en basklasspekare vill vi ibland ta reda på om den i själva verket hänvisar till en viss härledd klass. for ( Employee const* e : v ) CEO* ceo dynamic_cast <CEO*>(e) ; if ( ceo!= nullptr ) cout << ceo->bonus(); cout << e->salary() << endl;

31 / 38 Dynamisk typomvandling (referens) När vi har en basklassreferens vill vi ibland ta reda på om den i själva verket hänvisar till en viss härledd klass. void print_salary( Employee const& e ) cout << e.salary(); CEO& ceo dynamic_cast <CEO&>( e ) ; // may throw std::bad_cast cout << ceo.bonus(); try CEO ceo... ; print_salary(ceo); catch(std::bad_cast const& e) cerr << e.what() << endl;

32 / 38 Abstrakt klass (= 0) Vi kan i basklassen säga att det inte finns någon lämplig implementation av en virtual funktion. Då måste varje härledd klass tillhandahålla en egen implementation. Funktionen blir pure virtual och basklassen blir abstrakt. class Employee : public Person // abstract class due to...... virtual int salary() const = 0; //...pure virtual function... ; Employee e...; // Compilation error, incomplete class Employee* e new CEO...;

33 / 38 Minneshantering med polymorfi Vi måste som vanligt ta bort allt vi skapat med new, men...? vector <Employee*> v; v.push_back(new Employee...); // Compilation error, incomplete class v.push_back(new Programmer...); v.push_back(new CEO...); v.push_back(new Consult...);... for ( Employee const* e : v ) delete e; // Endast destruktorn för Employee!

34 / 38 Virtuell destruktor Vi behöver göra även destrukton virtual! class Employee : public Person public:... virtual ~Employee() = default;... for ( Employee const* e : v ) delete e; // Varje destruktor anropas, den mest härledda först!

35 / 38 Smartpekare - unique_ptr I standardbiblioteket finns speciella klasser för att hålla reda på pekare som en resurs. Klasserna unique_ptr och shared_ptr! vector <unique_ptr <Employee >> v; v.push_back(unique_ptr <Employee >new Employee...); // Same as below... v.push_back(make_unique <Employee >(...)); //...but this is safer! v.push_back(make_unique <CEO >(...));... // Destructor for vector start destructor for stored unique_ptr's!

36 / 38 Egen standardbaserad undantagsklass Vi kan skapa egna typer av undantag genom att ärva från ett standardundantag! noexcept anger att undantag inte slängs. class Stack_Error : public std::logic_error public: using std::logic_error::logic_error; ; class Code_Error : public std::exception public: Code_Error(int code) noexcept : exception, codecode const char* what() const noexcept return ""; int get_error_code() const return code; private: int code; ;

37 / 38 Överkurs: Interface Ibland vill vi bara bestämma vilka operationer som ska gå att utföra på en viss typ av objekt. Vi bestämmer objektets gränssnitt (interface). I C++ kan vi då skapa en helt abstrakt klass (enbart virtual funktioner): class Stack_Interface public: virtual void push(int value); virtual void pop(); virtual int& top(); virtual int top() const; virtual bool empty() const; ; class Linked_Stack : public Stack_Interface... class Vector_Stack : public Stack_Interface... void use_stack(stack_interface& stack); // Pass in any type of stack!

38 / 38 Överkurs: Non virtual interface (NVI) Ibland rekommenderas att virtual funktioner placeras privat. Det gör det enklare att ändra hur klassen löser problem internt utan att ändra på hur den används. class Stack_Interface public: void push(int value); void pop();... private: // The v_ prefix is to avoid clash with public name virtual void v_push(int value); virtual void v_pop();... ;

Klas Arvidsson Institutionen för datavetenskap www.liu.se