The coupling between object classes (CBO) is a metric proposed by Chidamber & Kemerer to measure for a class to how much other classes it is coupled. A coupling means that an object of one class use methods or properties of an object in another class.
The polymorphic factor (PF) is a metric proposed by Abreu & Melo to measure how much a derived type overrides a method from the base class. It's calculated by counting the number of overridden methods compared to the number of methods.
These are independent measures, so in theory you can find any kind of relationship. But let's have a look at an an example to show how they relate in practice.
Suppose you have classes for representing different shapes (Circle
, Square
, etc...) and a class Figure
, composed of several shapes. Figure
has a draw()
function that invokes a drawing method for each of its shapes.
- Uggly implementation: each shape as an own independent class with own specific drawing function (e.g.
draw_circle()
, draw_square(
), ...). Figure
must then be coupled to all the shapes, with a lot of conditionals to cope with the different shapes. Every time you add a new shape, you add a new coupling.
- CBO = N, where N is the number of shapes.
- PF = 0 because there's no inheritance and hence no overriding.
- Polymorphic implementation: each shape inherits from a superclass
Shape
and overrides the polymorphic draw()
function. Figure
only knows about Shape
.
- CBO = 1, because
Figure
only invokes the draw()
on a Shape
object .
- PF tends to 100% (precisely it's
N/(2+N)
because Figure::draw()
and Shape::draw()
are no overrides, but Shape::draw()
is overridden by N shapes
The common assumption is that a system with low coupling is easier to maintain. Therefore, many design patterns intend to reduce coupling. In most of the cases, polymorphism is the enabler for a decoupling.
Abstraction is the key, not the language feature used to implement it. Interface inheritance and normal inheritance are two ways to achieve abstraction. Interface inheritance requires you to provide an implementation for the interface functions (i.e. to provide an override for abstract functions which are not defined). It hence increases mathematically PF. However, some languages like C++ don't have interfaces but use pure virtual functions eventually with multiple inheritance to do the same, with identical PF. In our example, the inheritance is the enable for reducing coupling.