Typing Issues and LSP David Rabinowitz Object Oriented
Typing Issues and LSP David Rabinowitz Object Oriented Design Course
Typing l Static typing l Dynamic typing • Reliability • Catching errors early • Readability • Efficiency • Flexibility 2/25/2021 Object Oriented Design Course 2
In the real world l How do we add flexibility to static typing? • Genericity – C++ templates, Java Generics • Inheritance (including multiple inheritance) 2/25/2021 Object Oriented Design Course 3
Covariance Class Skier { Skier roommate; void share(Skier s); } Girl Boy Class Girl { Girl roommate; void share(Girl g); } Ranked. Girl Ranked. Boy Class Ranked. Girl { Ranked. Girl roommate; void share(Ranked. Girl rg); } 2/25/2021 Object Oriented Design Course 4
Covariance What happens when we do the following Skier s; Boy b; Girl g; b = new Boy(); g = new Girl(); s = b; s. share(g); l 2/25/2021 Object Oriented Design Course 5
Covariance l l What about multiple hierarchies? Does it solve the problem? 2/25/2021 Skier Room Girl. Room Ranked. Girl RGRoom Object Oriented Design Course 6
Descendant Hiding l How can a class hide its parent’s method? Polygon + add. Vertex() Rectangle - VERTICES=4 - add. Vertex() 2/25/2021 Bird + fly() Ostrich - fly() Object Oriented Design Course 7
Solutions l Some languages allow you to redeclare methods • No Girl. share(Skier) l Java and C++ do not allow this • Need to check the validity at runtime • if(skier instnaceof Girl) {…} else throw… 2/25/2021 Object Oriented Design Course 8
The Liskov Substitution Principle If for each object o 1 of type S there is an object o 2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o 1 is substituted for o 2 then S is a subtype of T. Barbara Liskov, 1988 2/25/2021 Object Oriented Design Course 9
LSP in plain English Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it 2/25/2021 Object Oriented Design Course 10
What’s wrong with this? void Draw. Shape(const Shape& s) { if (typeid(s) == typeid(Square)) Draw. Square(static_cast<Square&>(s)); else if (typeid(s) == typeid(Circle)) Draw. Circle(static_cast<Circle&>(s)); } 2/25/2021 Object Oriented Design Course 11
Things Are Not Always That Simple Consider the following class: class Rectangle{ public: void Set. Width(double w) {_width=w; } void Set. Height(double h) {_height=w; } double Get. Height() const {return _height; } double Get. Width() const {return _width; } private: double _width; double _height; }; 2/25/2021 Object Oriented Design Course 12
Square l We want to add a Square object l And the trivial implementation is: • Naturally derives Rectangle void Square: : Set. Width(double w) { Rectangle: : Set. Width(w); Rectangle: : Set. Height(w); } void Square: : Set. Height(double h) { Rectangle: : Set. Height(h); Rectangle: : Set. Width(h); } l Do you see any problem ? 2/25/2021 Object Oriented Design Course 13
LSP is broken! void g(Rectangle& r) { r. Set. Width(5); r. Set. Height(4); assert(r. Get. Width()*r. Get. Height())==20); } l A square object is not Rectangle object! • Their behavior is different 2/25/2021 Object Oriented Design Course 14
The Liskov Substitution Principle l l Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it Use inheritance carefully! 2/25/2021 Object Oriented Design Course 15
- Slides: 15