In Object Orientation, does an inheritance violate encapsulation?

Asked

Viewed 569 times

4

According to the book Design Standards written by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, make a statement:

"...inheritance violates the encapsulation."

Below is the paragraph containing this statement:

"... class inheritance also has some disadvantages. First, you cannot change the implementations inherited from ancestral classes at runtime, because inheritance is defined at compile time. Second, and usually this is the worst, ancestral classes often define at least part of the physical representation of their subclasses. Because inheritance exposes to a subclass the implementation details of their ancestors, it is often said that "inheritance violates the encapsulation" [Sny86]. The implementation of a subclass thus becomes so tied to the implementation of its mother class that any change in its implementation will force a change in that."

I couldn’t visualize this statement in practice. How does inheritance violate encapsulation? To further elucidate the understanding, an example that justifies this statement is welcome.

4 answers

8


This means that the coupling is strong and any code change in the base class affects the subclasses.

Therefore, it is not recommended to make the inheritance to reuse code. Because if a function needs to be changed in the original class, it will affect all daughters and the easy solution would be to violate encapsulation (making it protected or public something that would make more sense as private).

In many cases today, composition is recommended in place of inheritance to structure a code. The goal is to delegate smaller parts to a class that is part of the larger class.

For example, creating the Booking class and the Purchase class to be part of the Transaction class. In this case, it leaves all functions well separated and with well-defined behaviors.

4

Inheritance, as taught in OO in the 1990s (at the time they said OO would end world hunger), has surprisingly few legitimate uses. I would not use the expression "violates encapsulation", I would say rather that the inheritance "Engessa" the subclasses. "90s" Delphi-type languages, which only had inheritance as a means of code reuse, had deep class hierarchies in their framework (came up to a Chart in the product box, size A3, to paste on the wall), and broke everything with each new version.

It gets even more left-handed when multiple inheritance is allowed. That thing about "Square is subclass of Rectangle but also subclass of Polygonoregular"... then "Circle" should be subclass of "Polygonoregular" or not? At least they discovered in the 1990s that multiple inheritance was not a good idea, and the only really legitimate use was adherence to interfaces, that is, simple inheritance of a concrete class and multiple inheritance of purely abstract classes (Java has always been like this).

Sometimes that cast is perfectly adequate. In all the visual frameworks I know, each screen control is descended from a View class (Uiview on iOS, View on Android, etc.) In this case the inheritance is appropriate because the derived views have to rigidly fit the protocols and the functioning of the base View; and the base View implements the full basic functionality (it is it, not the derivative, that will "chat" with the video driver, etc.) If the View changes its modus operandi, it is legitimate and desirable to "break" all derivatives of View, preferably at compile time, so that they can be retrofitted.

But in most cases this hierarchical inheritance is a bad way to reuse code. Even the legacy of interfaces is obsolete, the "protocols" of Objective-C/Swift or "Duck Typing" of interpreted languages are much better. These languages also allow adding methods to a class without needing to define a subclass ("composition"). These features allow frameworks with "shallow" hierarchies. as is the case with Apple’s Uikit: https://finalizedotcom.files.wordpress.com/2012/12/uikit_classes.jpg

In summary, the overuse of inheritance was a consequence of the few resources of the available languages, the "novelty" of OO techniques, and the misunderstanding of the "real" OO as implemented in Smalltalk.

  • Very enlightening answer. Practically a history lesson! :)

4

We have to look at this discussion from the point of view of what it is encapsulation:

A mechanism to restrict access to class items

Encapsulation allows you to create an isolated implementation, so you can test alone and ensure that changes to the implementation (without changing the interface) have an impact zero in the rest of the system.

The opposite of this, just to give you a contrast, is you change a line of code and have to test half the system because of an extremely bad code coupled.

With this in mind, inheritance violates encapsulation in the sense that change in a superclass has the potential to affect all subclasses.

Think of the case where a superclass is used in multiple projects and now all of them will need to be updated and tested again.

In general, this does not occur if a superclass has limbs private (private). On the other hand, when we talk about members that can be accessed by subclasses (protected, for example) we have to understand that from the point of view of the subclass, protected and public are the same thing, so it’s like there’s no encapsulation.

Finally, using inheritance in wrong contexts (not that it’s easy to know) quickly leads you to:

Look how cool my "super class" that my 10 colleagues can just extend and have almost everything implemented "for free".

To, after a while:

Putz! I have to change this abstract class crap again, ask my 10 colleagues to update their implementations, test everything again and require all the system modules to be updated at the same time in production!

  • +1, just a doubt, in the last paragraph, you meant "private" there as translation of private right?

  • 1

    @Diegof that’s right

3

In some moments you may end up falling into situations where the internal implementation of the mother class will generate strange behaviors when you overwrite some method of it.

Ex: Case that generates Stackoverflow

public class InheritanceOverflow {

  public static class Parent {

    public void foo() {
      bar();
    }

    public void bar() {}
  }

  public static class Child extends Parent {
    @Override
    public void bar() {
      // Não há como saber nesse ponto que o método foo chama o método bar
      // isso irá gerar uma recursão infinita
      foo();
    }
  }

  public static void main(String[] args) {
    new Child().bar();
  }
}

Basically this example breaks the encapsulation because you have to know which internal implementation of the mother class to be able to solve this problem.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.