0

I've been practicing inheritance and I found myself asking what a "has-a" relationship is really about.

If I have a class circleType and I want to create a class cylinderType, whats the difference between deriving cylinderType from circleType and just including a circleType object member in the definition of cylinderType

class cylinderType :
public circleType
{
public:
    cylinderType();
    ~cylinderType();

private:
    double * height;
};

OR:

class cylinderType
{
public:
    cylinderType();
    ~cylinderType();

private:
    circleType baseOfCylinder;
};
Cory S.
  • 3
  • 3
  • 3
    Is a cylinder really a type of circle? – Alex Johnson Jul 18 '18 at 19:48
  • the base of a cylinder is a circle. – Cory S. Jul 18 '18 at 19:50
  • Exactly. That tells me that the second option above is the best reflection of the relationship between a circle and a cylinder. – Alex Johnson Jul 18 '18 at 19:52
  • 4
    The point I believe @AlexJohnson is trying to make is the first example violates the [Liskov Substitution Principle](https://stackoverflow.com/questions/56860/what-is-an-example-of-the-liskov-substitution-principle). If you cannot use a cylinder as a circle, it should not be a circle. – user4581301 Jul 18 '18 at 19:53
  • 1
    In general, the notable difference is that "is-a" will inherit interface. "has-a" will not. In your specific example, cylinder has-a circle, but cylinder is-NOT-a circle. – Drew Dormann Jul 18 '18 at 19:53

1 Answers1

6

Prefer composition to inheritance when the is-a relationship doesn't hold. In this case, a cylinder isn't a type of circle, so (public) inheritance isn't appropriate.

Remember, a class that inherits publicly from another class can be used anywhere the parent can be used. For example, given the definitions in the OP, the following is totally valid, even though it doesn't really make much sense to calculate the area of a cylinder:

double area(const circleType& circle)
{
    return PI * circle.radius() * circle.radius();
}

int main()
{
    cylinderType cylinder;
    std::cout << area(cylinder);
}
Miles Budnek
  • 28,216
  • 2
  • 35
  • 52