Composition vs. Inheritance

 

UML Basics:

 

Classes:

Class Name

 

Attributes – Private  Members

 

Interface – Public Methods

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


-, +, and # denote private, public, and protected member respectively

static members are underlined

 

Objects:

 

Object Name: <type>

 

Attribute values

 
 

 

 

 

 

 

 

 


Associations:

 

Relationships between classes (or objects) are called associations and denoted by solid line connecting the classes

 

 

 

 

 

 


Associations can be further specified by assigning roles to the classes or objects involved and naming these roles:

 

 

 

 

 

 

The "part-whole" relationship is a special association, called aggregation. There are two types of aggregation:

shared aggregation or just aggregation: the part may belong to more than one aggregate at the same time, denoted by hollow diamond at the aggregate side

 

 

 

 

 


Aggregation is implemented with references (or pointers) to component object

 

composition aggregation or just composition: the part belongs to only one aggregate, denoted by solid diamond on the aggregate side

 

 

 

 


Composition is implemented by defining the part object as a member of the aggregate object.

 

The "is-a" relationship—a relationship between a special and a general case—is called generalization and is denoted by a hollow arrow pointing to the super-class.

 

 

 


 

Generalization is implemented by inheritance.

 

 

For a brief overview of UML Borland UML Tutorial: http://bdn.borland.com/article/0,1410,31863,00.html

(For more on UML see the OMG webpage: http://www.uml.org/

 


Example: Point—Circle—Cylinder

 

(i)                 Composition

 

 

 

 

 

 


(ii)               Inheritance

 

 

 

 

 


Table: Point-Circle-Cylinder Composition – file summary

 

File Name

Description

point.h

Point class definition;

represents [x, y] coordinate pair as private data members.

point.cpp

Point class member-function definitions.

circleComposition.h

CircleComposition class with data member center of type Point;

circleComposition.cpp

CircleComposition class member-function definitions.

cylinderComposition.h

CylinderComposition class derived from class CircleComposition

cylinderComposition.cpp

CylinderComposition class inherits from class CircleComposition.

cylinderTestComposition.cpp

Testing class CylinderComposition.


Table: Point-Circle-Cylinder Hierarchy – file summary

 

File Name

Description

Point-Circle-Cylinder Hierarchy with private data members

point.h

Point class definition;

represents [x, y] coordinate pair as private data members.

same as for composition

point.cpp

Point class member-function definitions.

same as for composition

circle.h

Circle class derived from Point class;

adds private radius to base class [x,y] coordinates

circle.cpp

Circle class member-function definitions.

cylinder.h

Cylinder class derived from class Circle

adds private height to radius and [x,y] coordinates of base class

cylinder.cpp

Cylinder class inherits from class Circle.

cylinderTest.cpp

Testing class Cylinder.

Point-Circle Hierarchy with protected data members

pointProtected.h

PointProtected class definitions

represents an [x,y] coordinate pair as protected data members.

pointProtected.cpp

PointProtected class member-function definitions

circleProtected.h

// CircleProtected class derives from PointProtected class

// adds private radius to protected [x,y] coordinates of base class

// expanding the hierarchy with a CylinderProtected class in the same style

// requires the private radius to become protected

circleProtected.cpp

CircleProtected class member-function definitions.

circleTestProtected.cpp

Testing class CircleProtected.


 

 

Software Engineering Criteria

 

General Criteria:

 

Maintainability: ease of maintaining the code

Reusability: ability to extensively reuse existing code

Scalability (used also for hardware and generally for complex systems): ability of a system to add or remove components to accommodate new or growing functional requirements.   

 

 

More Specific Criteria:

 

Older Criteria:

Cohesion: relatedness of the steps belonging to a specific code segment/module;

High cohesion modules perform just one task and are easy to name, typically with a verb-plus-noun combination, e.g. getDate(), insertItem(), findItem() etc. as opposed to low cohesion modules that require several verbs and nouns, e.g. sortAndPrintIArray().

Cohesion is not a very strong criterion in that it is difficult to characterize numerically.

Coupling: describes the data flow between client (calling environment) and server (function). Coupling intensity can be measured by the number of values passed from client to server and vice versa.

Low coupling, i.e. passing of a small number of values, indicates low dependency and is of course a desirable property.

Coupling is a stronger criterion than cohesion.

 

Relatively New Criteria:

Information Hiding/Encapsulation: (often used interchangeably, although some authors differentiate between the two, but there is no universal agreement on the differences) refers to hiding the design decision for data members and methods that is most likely to change.  For instance the coordinates of a point are best hidden becuase the design decision may change,  e.g. from Cartesian to Polar coordinates, but the getPointCoordinates() method should still look the same.  Thus only the private data representation and the method definition will be affected by the change, but none of the modules using the class or method. 


Compare & contrast the composition and inheritance implementation with respect to

·        efficiency – same, getter, setter, constructors of superclass used.

·        cohesion--same

·        coupling—inheritance has higher coupling than composition because the methods of the derived class use methods of the base class; thus small changes in the base class will break the code of the derived class.

·        scalability—inheritance scales better; composition requires inclusion of overloaded getter/setter methods to access private data members of the class type. The latter would be the be an object of the super-class in inheritance and therefore the subclass will have inherited the setter/getter methods. Inheritance also makes it possible to use dynamic binding and polymorphism, e.g. a dynamic binding call that uses a pointer of super class type will work correctly for any subclass that was added later on.

·        maintainability—inheritance scales better for same reason as in previous paragraph.

 

For further examples and discussion on composition vs. inheritance see the Venners' article "Inheritance vs. Composition", Java World, October 1998. the examples are in Java but are of course just as valid in C++; the difference being just a slight difference in syntax)

 

Compare & contrast the implementation with private and protective data members with respect to:

·        efficiency—protected version slightly more efficient because it   eliminates the need of calls to setter/getter and constructors of super-class

·        cohesion—same

·        coupling—protected has higher coupling; derived class methods operate on super-class data-members, i.e. the derived class needs knowledge of base class internals.

·        scalability—private version scales better because interaction between classes relies on interface only; thus changes within a base class do not affect methods in the derived classes.

 

In contrast to this the protected version does not use the getter/setter methods of the base class but operates directly on data members of the base class; Thus the methods in the derived classes need to know the implementation in the base class not just its public interface. Changes in the base class lead to code re-writes in the derived class àit becomes more difficult to grow/shrink the program, e.g.

o       setter methods in derived class do not rely on setter methods in base class and may introduce illegal value

o       to avoid this one needs to consistently repeat relevant code from the base class, e.g.

 

CircleProtected::setRaduis(double radiusValue){

    radius = radiusValue <0.0 ? 0.0: radiusValue;

}

 

code becomes "fragile or brittle".

 

·        maintainability—protected version more difficult to maintain for same reasons as in previous paragraph.