Skip to main content

Section 17.5 Composition of Classes

We already have built a class Point that represents a point in 2D space. Now we would like to build a class to represent a Circle. A circle is defined by its center and its radius - given those two pieces of information, we can calculate anything else we might need like its area or diameter.
One way we could approach Circle, would be to build it from primitive data:
      classDiagram
          class PrimitiveCircle{
            -m_radius : double
            -m_centerX : double
            -m_centerY : double
            +getRadius() double
            ...otherFunctions()
          }
      
Figure 17.5.1. A Circle class that stores all its data as doubles
This could work just fine. But, as the circle gets more complex, it is likely going to have to implement some of the same logic as our existing Point class. For example, if I want to know if two circles overlap, I could see if the distance between their centers is less than the sum of their radii. To do that, I would need to use the distance formula. Point already has a method to do the distance formula - copy/pasting that code into Circle sounds like the wrong approach.

Insight 17.5.1.

Remember: copy/paste is a design flaw. We want to avoid repeating significant pieces of program logic.
A better way to make use of our existing Point code is to define our Circle class in terms of a Point. We can define a Circle as something that has a Point and a radius:
      classDiagram
          class Circle{
            -m_radius : double
            -m_center : Point
            +getRadius() double
            ...otherFunctions()
          }
      
Figure 17.5.2. A Circle class that stores a Point and a double
Defining one class in terms of another is known as composition. Composition is one of the key ways object-oriented programming allows us to reuse code in new ways. Composition implies a has-a relationship with a strong sense of ownership. A Circle Point that is its center. That Point belongs to the Circle - if the Circle goes away, we would expect the Point to disappear with it.
A complete UML diagram of our data types would show both Point and Circle. We represent the relationship between them using a line that connects the two class diagrams. Finally, we place a filled diamond where the line meats the β€œowning” class. Since Circle β€œhas a” Point, we place the diamond next to the Circle box:
      classDiagram

          class Circle{
            -m_radius : double
            -m_center : Point
            +getRadius() double
            ...otherFunctions()
          }
          class Point{
            -m_x : double
            -m_y : double
            +getX() double
            +getY() double
            ...otherFunctions()
          }
          Circle *-- Point
      
Figure 17.5.3. A Circle class that has-a Point as a member

Checkpoint 17.5.1.

You have attempted of activities on this page.