Inheritance and Polymorphism in Object-Oriented Programming

Inheritance and Polymorphism in Object-Oriented Programming
Slide Note
Embed
Share

Inheritance allows the creation of new classes based on existing ones, sharing attributes and behavior. Polymorphism enables objects of different classes to be treated as instances of a common superclass. This lecture explores the concepts of superclass, subclass, and how to use inheritance effectively in programming.

  • Inheritance
  • Polymorphism
  • Object-Oriented Programming
  • Classes
  • Code Sharing

Uploaded on Mar 09, 2025 | 0 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.

E N D

Presentation Transcript


  1. CS 132, Winter 2024 Lecture 19: Critters; polymorphism Thank you to Marty Stepp and Stuart Reges for parts of these slides

  2. Inheritance inheritance: A way to form new classes based on existing classes, taking on their attributes/behavior. a way to indicate that classes are related a way to share code between two or more related classes (a hierarchy) One class can extend another, absorbing its data/behavior. superclass (base class): Parent class that is being extended. subclass (derived class): Child class that inherits from the superclass. Subclass gets a copy of every field and method from superclass. Subclass can add its own behavior, and/or change inherited behavior. 2

  3. CS 132 Critters Ant Bird Hippo Vulture Cat (creative) behavior: eat fight getColor getMove toString eating food animal fighting color to display movement letter to display 3

  4. A Critter subclass public name : public Critter { ... } class Critter : public CritterBase { public: virtual bool eat(); virtual Attack fight(std::string opponent); // ROAR, POUNCE, SCRATCH virtual std::string getColor(); virtual Direction getMove(); // NORTH, SOUTH, EAST, WEST, CENTER virtual std::string getType() const = 0; virtual std::string toString(); }; 4

  5. How the simulator works "Go" loop: move each animal (getMove) if they collide, fight if they find food, eat Next move? to remember future moves% Simulator is in control! getMove is one move at a time (no loops) Keep state (fields) 5

  6. Development Strategy Do one species at a time in ABC order from easier to harder (Ant Bird ...) debug couts Simulator helps you debug fewer animals "Tick" instead of "Go" "Debug" checkbox Make your own main to call your member functions and print out what they return 6

  7. Critter exercise: Cougar Write a critter class Cougar: Method constructor Cougar() eat fight getColor Behavior Always eats. Always pounces. Blue if the Cougar has never fought; red if he has. Walks west until he finds food; then walks east until he finds food; then goes west and repeats. "C" getMove toString 7

  8. Ideas for state You must not only have the right state, but update that state properly when relevant actions occur. Counting is helpful: How many total moves has this animal made? How many times has it eaten? Fought? Remembering recent actions in fields is helpful: Which direction did the animal move last? How many times has it moved that way? Did the animal eat the last time it was asked? How many steps has the animal taken since last eating? How many fights has the animal been in since last eating? 8

  9. Cougar solution // Cougar.cpp Cougar::Cougar() { west = true; fought = false; } bool Cougar::eat() { west = !west; return true; } Attack Cougar::fight(std::string opponent) { fought = true; return POUNCE; } std::string Cougar::getType() const { return "Cougar"; } std::string Cougar::toString() { return "C"; } Direction Cougar::getMove() { if(west) { return WEST; } else { return EAST; } } std::string Cougar::getColor() { if(fought) { return "red"; } else { return "blue"; } } // Cougar.h #ifndef _cougar_h_ #define _cougar_h_ #include "Critter.h" class Cougar : public Critter { public: Cougar(); bool eat(); Attack fight(std::string opponent); std::string getType() const; std::string toString(); Direction getMove(); std::string getColor(); private: bool west; bool fought; }; #endif 9

  10. Vectors of Critters What if we want to store some of the Critters you are writing this week into a Vector? What type should this Vector store? 10

  11. Polymorphism polymorphism: Ability for the same code to be used with different types of objects and behave differently with each. Templates provide compile-time polymorphism. Inheritance provides run-time polymorphism. Idea: Client code can call a member function on different kinds of objects, and the resulting behavior will be different. 11

  12. Poly. and pointers A pointer of type T can point to any subclass of T. Employee* edna = new Lawyer("Edna", "Harvard", 5); Secretary* steve = new LegalSecretary("Steve", 2); World* world = new WorldMap("map-stanford.txt"); When a member function is called on edna, it behaves as a Lawyer. (This is because the employee functions are declared virtual.) You can not call any Lawyer-only members on edna (e.g. sue). You can not call any LegalSecretary-only members on steve (e.g. fileLegalBriefs). 12

  13. Polymorphism examples You can use the object's extra functionality by casting. Employee* edna = new Lawyer("Edna", "Harvard", 5); edna->vacationDays(); // ok edna->sue("Stuart"); ((Lawyer*) edna)->sue("Stuart"); // ok // compiler error You should not cast a pointer into something that it is not. It will compile, but the code will crash (or behave unpredictably) when you try to run it. Employee* paul = new Programmer("Paul", 3); paul->code(); // compiler error ((Programmer*) paul)->code(); // ok ((Lawyer*) paul)->sue("Marty"); // crash! 13

  14. "Polymorphism mystery" class Snow { public: virtual void method2() { cout << "Snow 2" << endl; } virtual void method3() { cout << "Snow 3" << endl; } }; class Rain : public Snow { public: virtual void method1() { cout << "Rain 1" << endl; } virtual void method2() { cout << "Rain 2" << endl; } }; 14

  15. "Polymorphism mystery" class Sleet : public Snow { public: virtual void method2() { cout << "Sleet 2" << endl; Snow::method2(); } virtual void method3() { cout << "Sleet 3" << endl; } }; class Fog : public Sleet { public: virtual void method1() { cout << "Fog 1" << endl; } virtual void method3() { cout << "Fog 3" << endl; } }; 15

  16. Diagramming classes Draw a diagram of the classes from top (superclass) to bottom. Snow Snow 2 Snow 3 method2 method3 Rain Sleet Rain 1 Rain 2 Snow 3 Sleet 2 / Snow 2 Sleet 3 method1 method2 (method3) method2 method3 Fog Fog 1 method1 (method2) method3 Sleet 2 / Snow 2 Fog 3 16

  17. Mystery problem Snow* var1 = new Sleet(); var1->method2(); // What's the output? To find the behavior/output of calls like the one above: 1. Look at the variable's type. If that type does not have that member: COMPILER ERROR. Execute the member. Since the member is virtual: behave like the object's type, not like the variable's type. 2. 17

  18. Example 1 Q: What is the result of the following call? variable Snow Snow* var1 = new Sleet(); var1->method2(); Snow 2 Snow 3 method2 method3 A. Snow 2 B. Rain 2 object Rain Sleet Rain 1 Rain 2 Snow 3 Sleet2/Snow2 Sleet 3 method1 method2 (method3) method2 method3 C. Sleet 2 Snow 2 Fog D. COMPILER ERROR Fog 1 method1 (method2) method3 Sleet2/Snow2 Fog 3 18

  19. Example 2 Q: What is the result of the following call? variable Snow Snow* var2 = new Rain(); var2->method1(); Snow 2 Snow 3 method2 method3 A. Snow 1 B. Rain 1 object Rain Sleet Rain 1 Rain 2 Snow 3 Sleet2/Snow2 Sleet 3 method1 method2 (method3) method2 method3 C. Snow 1 Rain 1 Fog D. COMPILER ERROR Fog 1 method1 (method2) method3 Sleet2/Snow2 Fog 3 19

  20. Example 3 Q: What is the result of the following call? variable Snow Snow* var3 = new Rain(); var3->method2(); Snow 2 Snow 3 method2 method3 A. Snow 2 B. Rain 2 object Rain Sleet Rain 1 Rain 2 Snow 3 Sleet2/Snow2 Sleet 3 method1 method2 (method3) method2 method3 C. Sleet 2 Snow 2 Fog D. COMPILER ERROR Fog 1 method1 (method2) method3 Sleet2/Snow2 Fog 3 20

  21. Mystery with type cast Snow* var4 = new Rain(); ((Sleet*) var4)->method1(); // What's the output? If the mystery problem has a type cast, then: 1. Look at the cast type. If that type does not have the method: COMPILER ERROR. (Note: If the object's type were not equal to or a subclass of the cast type, the code would CRASH / have unpredictable behavior.) Execute the member. Since the member is virtual, behave like the object's type. 2. 21

  22. Example 4 Q: What is the output of the following call? variable Snow Snow* var4 = new Rain(); ((Rain*) var4)->method1(); Snow 2 Snow 3 method2 method3 cast object A. Snow 1 B. Rain 1 Rain Sleet Rain 1 Rain 2 Snow 3 Sleet2/Snow2 Sleet 3 method1 method2 (method3) method2 method3 C. Sleet 1 D. COMPILER ERROR Fog Fog 1 method1 (method2) method3 Sleet2/Snow2 Fog 3 22

  23. Example 5 Q: What is the output of the following call? variable Snow Snow* var5 = new Fog(); ((Sleet*) var5)->method1(); Snow 2 Snow 3 method2 method3 A. Snow 1 B. Sleet 1 cast Rain Sleet Rain 1 Rain 2 Snow 3 Sleet2/Snow2 Sleet 3 method1 method2 (method3) method2 method3 C. Fog 1 D. COMPILER ERROR object Fog Fog 1 method1 (method2) method3 Sleet2/Snow2 Fog 3 23

  24. Example 6 Suppose we add the following method to base class Snow: virtual void method4() { cout << "Snow 4" << endl; method2(); } variable Snow Snow 2 Snow 3 method2 method3 What is the output? Snow* var8 = new Sleet(); var8->method4(); object Rain Sleet Rain 1 Rain 2 Snow 3 Sleet2/Snow2 Sleet 3 method1 method2 (method3) method2 method3 Answer: Snow 4 Sleet 2 Snow 2 (Sleet's method2 is used because method4 and method2 are virtual.) Fog Fog 1 method1 (method2) method3 Sleet2/Snow2 Fog 3 24

  25. Example 7 Q: What is the output of the following call? variable Snow Snow* var6 = new Sleet(); ((Rain*) var6)->method1(); Snow 2 Snow 3 method2 method3 A. Snow 1 B. Sleet 1 cast object Rain Sleet Rain 1 Rain 2 Snow 3 Sleet2/Snow2 Sleet 3 method1 method2 (method3) method2 method3 C. Fog 1 D. COMPILER ERROR Fog E. CRASH Fog 1 method1 (method2) method3 Sleet2/Snow2 Fog 3 25

  26. Pure virtual functions virtual returntype name(params) = 0; pure virtual function: Declared in superclass's .h file and set to 0 (null). An absent function that has not been implemented. Must be implemented by any subclass, or it cannot be used. A way of forcing subclasses to add certain important behavior. class Employee { ... virtual void work() = 0; // every employee does // some kind of work }; FYI: In Java, this is called an abstract method. 26

  27. Pure virtual base class pure virtual base class: One where every member function is declared as pure virtual. (Also usually has no member variables.) Essentially not a superclass in terms of inheriting useful code. But useful as a list of requirements for subclasses to implement. Example: Demand that all shapes have an area, perimeter, # sides, ... class Shape { // pure virtual class; extend me! virtual double area() const = 0; virtual double perimeter() const = 0; virtual int sides() const = 0; }; FYI: In Java, this is called an interface. 27

  28. Multiple inheritance class Name : public Superclass1, public Superclass2, ... multiple inheritance: When one subclass has multiple superclasses. Forbidden in many OO languages (e.g. Java) but allowed in C++. Convenient because it allows code sharing from multiple sources. Can be confusing or buggy, e.g. when both superclasses define a member with the same name. Example: The C++ I/O streams use multiple inheritance: 28

More Related Content