layout: true [UML Essentials]: http://www.tbfe.de/data/uploads/diagrams/uml-classesandrelations.png "UML Classes and Class Relations" --- class: titlepage, center, middle, subsection # Composition, Inheritence, and Templates ??? Testing Notes ... ``` with a fragment of code ... ``` --- name: content class: itoc # Composition, Inheritance, and Templates All these mechanism are about building a larger system from smaller parts. The first two are the classical ones and available in many OO-languages like Java, Python ... * Composition: parts get assembled into a composite. * Inheritance: A general concept is specialised. The third is more specific for C++. * C++-Templates: Flexible class cominations at compile-time. --- layout: true .left-column[ ## Composition ### - Basics ] .right-column[{{content}}] --- It's up to the composite to decide to which degree it reveals its parts to its clients. * It may hide all of its parts but (behind the scene), * or delegate some of its operations to its parts. Parts **may or may not** be re-used in several independant composites: * Reusing a parts in several composites obviously helps to ensure the DRY principle. * Just partioning large composites into parts only used ionce (there) may overall improve structure. In so far parts play a similar role as using subroutines for control flow. --- layout: true .left-column[ ## Composition ### - Basics ### - UML Notation ] .right-column[{{content}}] --- The UML Notation for composition is: * Two classes denoted by rectangles are connected with a straight line. .red[*] * The line ends unadorned where connected to the part. * The line ends with a filled diamond where it ends at the composite. .red[\*\*] See *Composition* [in Info-Graphic][UML Essentials]. .footnote[ .red[*] Optionally the the part class symbol (rectangle) may be drawn ''inside'' the composite class symbol. ] .red[\*\*] From the UML notation used **Composition** is close to **Aggregation**, but only the former couples life-times of objects. ] --- layout: true .left-column[ ## Composition ### - Basics ### - UML ### - C++ ] .right-column[{{content}}] --- There are actually two ways to express composition in C++: * By an explicite data member. * By a private base class. As long as there is no other reason to use a base class, an explicite data member should be preferred, despite delegation requires litte more work in this case. .pull-left[ ~~~ class Composite { Part myPart; // ... }; ~~~ ] .pull-right[ ~~~ class Composite : private Part { // ... }; ~~~ ] --- layout: true .left-column[ ## Composition ### - Basics ### - UML ### - Syntax ### - Example ] .right-column[ {{content}}] --- #### Explicit Data Member This is the part: ~~~ class Point { double x, y; // rectangular coordinates ... }; ~~~ It is used here: ~~~ class Line { Point start, end; // ... }; ~~~ And it is reused here: ~~~ class Triangle { Point corner[3]; // ... }; ~~~ --- #### Composition - C++ - Private Base Class - Example This is the part: ~~~ class Engine { public: void start(); ... }; ~~~ Used only once here: ~~~ class Car : private Engine { public: void start(); // ... } ~~~ --- #### Composition - C++ - Explicit Member- Example As explicite member: ~~~ class Car { Engine motor; public: void start(); // ... } ~~~ A ship might have two engines: ~~~ class Ship { Engine leftMotor; Engine rightMotor; public: void start(); // ... }; ~~~ **This cannot be achieved (easily) by using private base classes!** ??? In fact there is a way to build two ``Engine``s into a ``Ship`` using private base classes. But it requires two intermediate classes: ~~~ class LeftEngine : public Engine { // ... }: class RightEngine : public Engine { // ... }; class Ship : private LeftEngine , private RightEngine { // ... public: void start() { LeftEngine::start(); RightEngine::start(); }; ~~~ --- .left-column[ ## Composition ### - Basics ### - UML ### - C++ ### - Delegation ] .right-column[ Delegation in case of composites means: * An operation requested from the composites. * Is carried out fully by the part. The general scheme to delegate ``doSomething`` to the part looks like follows: * If the part is a private base class ``Part``: ~~~ void Composite::doSomething() { Part::doSomething(); } ~~~ * If the part is a member ``m``: ~~~ void Composite::doSomething() { m.doSomething(); } ~~~ ] --- #### Composition - Delegation - Example Delegations might have to forward arguments and return values: * Assume to start the engine of a car a secret token read from the ignition key RFID transponder must be supplied. * Further assume the return value of ``Engine::start`` shows whether the token was accepted and the engine actually started up ~~~ class Engine { // ... public: bool start(unsigned token); }; ~~~ --- #### Composition - Delegation - Example .pull-left[ If the ``Engine`` is a member ``motor`` delegation requires this boiler-plate code: ~~~ class Car { Enginge motor; public: bool start(unsigned token) { return motor.start(token); } }; ~~~ ] .pull-right[ If the ``Engine`` is a private base class the following is sufficient: ~~~ class Car : public Engine { public: using Engine::start; }; ~~~ ] --- #### Composition - Delegation - Example If there is anything else to do in the delegation, besides forwarding to the part, the difference does not matter much any more .pull-left[ * With an explcite member: ~~~ bool Car::start(unsigned token) { // ... before starting ... if (!motor.start(token)) { // ... failed to start return false; } // ... after starting .... return true; }; ~~~ ] .pull-right[ * With a private base class: ~~~ bool Car::start(unsigned token) { // ... before starting ... if (!Engine::start(token)) { // ... failed to start return false; } // ... after starting ... return true: }; ~~~ ] --- #### Starting two motors: ~~~ bool Ship::start(unsigned token) { // ... before starting left ... const bool leftRunning{!eftMotor.start()}; const bool rightRunning{rightMotor.start()}; if (leftRunning && rightRunning) { // ... after starting both ... return true; } if (leftRunning || rightRunning) { // ... after starting at least one ... return true; } // ... failed to start any return left; } ~~~ --- .left-column[ ## Inheritance ### - Basics ] .right-column[ Inheritance usually makes sense only if there is more than one specialisation ... ... **and** if spezialisations may be handed to clients expecting the general concept. * This is also known as: * Substitutability * Liskov Substitution Principle .red[*] * LSP (as shorthand of the above) ] .footnote[ .red[*] Named after Barbara Liskov who first described it as one of the desirable quality criteria for OO-Designs. ] --- .left-column[ ## Inheritance ### - Basics ### - UML Notation ] .right-column[ The UML Notation for inheritance is: * Two classes denoted by rectangles are connected with a straight line. * The line ends unadorned where connected to the specialisation. * The line ends with a hollow triangle diamond where it ends at the generalisation. (One triangle's tip points to the class while the connecting line ends in the middle of its base.) See *Inheritance* [in Info-Graphic][UML Essentials]. ] --- .left-column[ ## Inheritance ### - Basics ### - UML Notation ### - C++ ] .right-column[ In C++ the LSP only becomes effective through public base classes! * This is inheritance: ~~~ class Derived : public Base { // ... }; ~~~ * These are **not** inheritance: ~~~ class Derived : private Base { // ... }; ~~~ ~~~ class Derived : protected Base { // ... }; ~~~ ~~~ class Derived : Base { // ... }: ~~~ ] --- .left-column[ ## Templates ### - Basics ] .right-column[ A template is a class which is parameterized in one or more * Types * Constants * Policies During implementation there are only place-holders in effect. The client supplies the actual values during instantiation. The most typical use is for STL container classes, like * ``std::vector`` * ``std::list`` * ... But there are many other practical applications. ] --- .left-column[ ## C++ Templates ### - Basics ### - UML ] .right-column[ The UML notation for a template is * an ordinary class symbol (rectangle) * with another class symbol overlayed, slightly shifted top-right [See Info-Graphic: UML Classes and Relations](http://www.tbfe.de/data/uploads/diagrams/uml-classesandrelations.png) ] ] --- .left-column[ ## Templates ### - Basics ### - UML ### - C++ ] .right-column[ Templates come in two flavours: * Template functions * Template classes In both case declarations and definitions need to introduce formal names for the parametrized information. * This is done after the keyword ``template`` in a list enclosed in angle brackets. * The parametrization applies to the function or class that directly follows. * Therefore needs to be repeated for member function defined outside of their class. ] --- #### Template - Function - Example (Definition) The following function has three arguments, the first two are fixed in type, the third is parametrized. In the function implementation ``T``may be used as any ordinary type, e.g. to allocate a local temporary. ~~~ template
void foo(int x, char *cp, T other) { T tmp{other}; } ~~~ --- #### Template - Function - Example (Call) When calling this function, the type of the third argument is used by the compiler to deduce the type of ``T``: * In this call ``T`` would be deduced to have type ``double``: ~~~ double d; foo(12, "hello", d); ~~~ * In this call ``T`` would be deduced to have type ``std:string``: ~~~ std::string s; foo(12, "hello", s); ~~~ --- #### Template - Class - Example (Definition) The following class is parametrized in a type and a size. An example use is to define an array inside the class: ~~~ template
class RingBuffer { ElementType data[MaxElements]; // ... } ~~~ --- #### Template - Class - Example (Instantation) When instantiating ``RingBuffer`` objects the template arguments must be given concrete values: * In this instantiation there would be 20 Elements of type ``int``: ~~~ RingBuffer
rb; ~~~ * In this instantiation there would be 100 Elements of type ``std::string``: ~~~ RingBuffer
rb2; ~~~ --- # Resources --- name: info-graphics ## Info-Graphics [UML: Classes and Relations][UML Essentials] ---