As the Gang of Four states it in "Design Patterns": "it's often said that 'inheritance breaks encapsulation'", paraphrasing Snyder in "Encapsulation and Inheritance in Object-Oriented Programming Languages".
However, each time I read that "inheritance breaks encapsulation", the reasons behind this claim are either vaguely explained, or explained with an example of the Fragile Base Class problem.
While reading papers, I have the feeling that the only property of inheritance that really breaks encapsulation is downcalls, a feature allowed by open recursion (dynamic dispatch on this
) and defined as "when a superclass method calls a method that is overridden in the subclass", according to Ruby & Leavens in "Safely Creating Correct Subclasses without Seeing Superclass Code".
Moreover, open recursion apparently is the cause of the Fragile Base Class problem, according to Aldrich in "Selective Open Recursion: A Solution to the Fragile Base Class Problem".
So, if the Fragile Base Class problem is the only reason why "inheritance breaks encapsulation", it would be clearer to say that downcalling breaks encapsulation. Since some solutions exist to avoid downcalls while still using inheritance, inheritance itself is not really involved in breaking encapsulation. Moreover, the Delegation pattern proposed by the Gang of Four to get rid of inheritance can also allow open recursion and downcalls, since the delegator's context (this
) is used by the delegate (which can lead to a kind of Fragile Delegate Class problem).
Hence my question is:
Is the Fragile Base Class problem the only reason why it is said that "inheritance breaks encapsulation"?
You just need to be careful when and how you use inheritance.
In many languages, you can inherit (according to the language rules) from a base class by default, unless the developer of the base class took steps to prevent it. But just because you can inherit, doesn't mean the base class was designed to work properly when subclassed.
And encapsulation doesn't work just at the moment. If I create a class, everything is nicely encapsulated, you create a subclass without my knowledge, and me, not being aware of it, make changes to my class that breaks yours. That can happen.
So you need a baseclass that was designed to be subclassed.