slicing
play

Slicing Imagine we have a hierarchy of shape shapes with the - PowerPoint PPT Presentation

Slicing Imagine we have a hierarchy of shape shapes with the following inherits members get_name(): circle triangle the name assigned to the shape get_area(): the area occupied by the shape We also provide swap(&,


  1. Slicing  Imagine we have a hierarchy of shape shapes with the following inherits members • get_name(): … circle triangle the name assigned to the shape • get_area(): the area occupied by the shape  We also provide swap(&, &) for exchanging two shapes of the same type  Let us implement bubble sort Th. Gschwind. Advanced Software Engineering with C++ Templates. 356

  2. Bubble Sort for a vector<shape*> void sort(vector<shape*> &v) { if (v.size() < 2) return ; bool rerun; do { rerun = false; for (size_t i = 0; i < v.size()-1; ++i) { if (v[i]->get_area() > v[i+1]->get_area()) { swap(*v[i], *v[i+1]); rerun = true; } } } while (rerun); }  When we invoke swap, we exchange the contents of the shapes at v[i] and v[i+1]  To do this, swap(shape&, shape&) is invoked Th. Gschwind. Advanced Software Engineering with C++ Templates. 357

  3. Bubble Sort for a vector<shape*> (cont’d) void swap(shape &s1, shape &s2) { shape t = s1; s1 = s2; s2 = t; }  Since the swap function only has space for a shape inside t, only the shape part of s1 is assigned to t  Only the shape part of s2 can be assigned to s1 • During runtime s1 and s2 can be objects of different types • It is not possible to assign the contents of a circle to a rectangle  Finally, the shape part of t is assigned to s2  Members (i.e., radius, sides a+b+c) used to compute the area of the shape are not swapped  Hence, only the name is swapped, and sort will not terminate, because the areas of the shapes are never swapped Th. Gschwind. Advanced Software Engineering with C++ Templates. 358

  4. Bubble Sort for vector<shape*> void sort(vector<shape*> &v) { if (v.size() < 2) return ; bool rerun; do { rerun = false; for (size_t i = 0; i < v.size()-1; ++i) { if (v[i]->get_area() > v[i+1]->get_area()) { swap(v[i], v[i+1]); // swap(*v[i], *v[i+1]); rerun = true; } } } while (rerun); }  We should have only exchanged the pointers in the vector  Providing swap for shapes, was probably misguided in the first place  It makes only sense to swap shapes of the very same type Th. Gschwind. Advanced Software Engineering with C++ Templates. 359

  5. Advanced Software Engineering with C++ Templates Liskov Substitution Principle Thomas Gschwind <thg at zurich dot ibm dot com>

  6. Liskov Substitution Principle Th. Gschwind. Advanced Software Engineering with C++ Templates. 361

  7. Squares and Rectangles  I had a colleague who was unsure whether to derive rectangle from square or vice-versa. What would you recommend to him? Implement a set of sample programs illustrating various options and your recommendation! The programs should demonstrate why your solution is better than the other solutions Th. Gschwind. Advanced Software Engineering with C++ Templates. 362

  8. Squares and Rectangles Shape inherits … Line Circle Triangle  Class hierarchy for a vector graphics program  We have an abstract class Shape from which various geometric shapes are being derived  Task: • Add the following classes: Square, Rectangle • Also add useful members like {get,set}_{width,height,length,size }, … Th. Gschwind. Advanced Software Engineering with C++ Templates. 363

  9. Liskov Substitution Principle If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behaviour of P is unchanged when o1 is substituted for o2 then S is a subtype of T. Put Simple: Every function/program must work the same when it is invoked with a subclass instead of the expected class. This is the responsibility of the subclasses! Th. Gschwind. Advanced Software Engineering with C++ Templates. 364

  10. Square  Rectangle class Rectangle { int w, h; public : Rectangle virtual void setWidth( int wi) { w=wi; } virtual void setHeight( int he) { h=he; } inherits }; Square class Square : public Rectangle { public : virtual void setWidth( int w) { Rectangle::setHeight(w); Rectangle::setWidth(w); } virtual void setHeight( int h) { setWidth(h); } }; Th. Gschwind. Advanced Software Engineering with C++ Templates. 365

  11. Square  Rectangle (cont’d)  What happens if we pass a Square to a function test expecting a Rectangle?  Can we expect the function test to know about Square?  Would it be OK if the function yields an unexpected outcome under the motto garbage-in garbage-out?  No! Because we claim that a Square is a Rectangle! void test(Rectangle &r) { Rectangle r.setWidth(5); r.setHeight(4); inherits assert((r.getWidth()*r.getHeight())==20); Square } Th. Gschwind. Advanced Software Engineering with C++ Templates. 366

  12. Square  Rectangle V2 class Rectangle { int w, h; public : Rectangle void setWidth( int wi) { w=wi; } void setHeight( int he) { h=he; } inherits }; Square class Square : public Rectangle { public : void setWidth( int w) { Rectangle::setHeight(w); Rectangle::setWidth(w); } void setHeight( int h) { setWidth(h); } }; Th. Gschwind. Advanced Software Engineering with C++ Templates. 367

  13. Square  Rectangle V2 (cont’d)  What happens if we pass a Square to a function test expecting a Rectangle?  The program works now as expected  However, since set_width/set_height are no longer virtual our Square is now a Rectangle ==> This is not the solution either void test(Rectangle &r) { Rectangle r.setWidth(5); r.setHeight(4); inherits assert((r.getWidth()*r.getHeight())==20); Square } Th. Gschwind. Advanced Software Engineering with C++ Templates. 368

  14. Rectangle  Square  Square has one field (height or width) Square  Rectangle adds another one for the other dimension inherits • Makes sense from a memory usage point of view Rectangle  Square has a method to set the length  Rectangle adds methods for height and width • Also makes sense from the methods they provide • A Square does not need set_height & set_width Th. Gschwind. Advanced Software Engineering with C++ Templates. 369

  15. Rectangle  Square class Square { Square int l; public : virtual void setLength( int le) { l=le; } inherits virtual int getLength() { return l; } Rectangle }; class Rectangle : public Square { // reuse length as height int w; public : virtual void setLength( int le) { Square::setLength(le); setWidth(le); } virtual void setHeight( int he) { Square::setLength(he); } virtual void setWidth( int wi) { w=wi; } }; Th. Gschwind. Advanced Software Engineering with C++ Templates. 370

  16. Rectangle  Square (cont’d)  We cannot pass a Square to the test function Square void test(Rectangle &r) { r.setWidth(5); r.setHeight(4); inherits Rectangle assert((r.getWidth()*r.getHeight())==20); }  What if test would take Squares? • No problem either, LSP fulfilled void test(Square &s) { s.setLength(5); s.setLength(4); assert((s.getLength()*s.getLength())==16); } Th. Gschwind. Advanced Software Engineering with C++ Templates. 371

  17. Rectangle  Square (cont’d)  Let us extend our Shape class hierarchy Square  Our customer requests a get_area() member int Square::get_area() { return l*l; } inherits int Rectangle::get_area() { return l*wi; } Rectangle void foo(Square &s) { assert((s.get_length()*s.get_length()) ==s.get_area()); } Th. Gschwind. Advanced Software Engineering with C++ Templates. 372

  18. Rectangle  Square (cont’d)  Let us extend our Shape class hierarchy Square  Our customer requests a get_area() member int Square::get_area() { return l*l; } inherits int Rectangle::get_area() { return l*wi; } Rectangle void test(Square &s) { assert((s.get_length()*s.get_length()) ==s.get_area()); } void oh_no_not_another_test() { Rectangle r(3,4); test(r); } Th. Gschwind. Advanced Software Engineering with C++ Templates. 373

  19. Square  Shape, Rectangle  Shape Shape inherits … Line Circle Square Rectangle Correct, don’t use deep class hierarchies just because it is “object - oriented” programming (is it?) or because it’s “cool” or “professional” (or whatever)! Th. Gschwind. Advanced Software Engineering with C++ Templates. 374

  20. Lessons Learned  Avoid code inheritance • People will nail you down on how the base class is implemented  If inheritance is needed define an interface • Now, only the documentation counts  Inherit the interface not the code  If code inheritance is needed, prefer the use of an interface plus use aggregation • Follow this advice especially when using Java • Yes, you need to type a bit more  If this is really (really?) not an option provide both an interface and a class to inherit from Th. Gschwind. Advanced Software Engineering with C++ Templates. 375

  21. Advanced Software Engineering with C++ Templates Exceptions Thomas Gschwind <thg at zurich dot ibm dot com>

  22. Exceptions  Error Handling  Exception Specification  Exception Discrimination  Cleaning up in C++ (a.k.a. finally )  Standard Exceptions Th. Gschwind. Advanced Software Engineering with C++ Templates. 377

Recommend


More recommend