Inheritance breaking encapsulation?

2020-06-04 02:16发布

问题:

People say inheritance breaks encapsulation, which i agree with. They say delegation is better- although the modifiers in delegation can also be public/protected.

So is the real reason why inheritance breaks encapsulation because of the "knock-on" effect of the public/protected modifiers from the super class being exposed to any new classes which extend the current subclass?

回答1:

Yes. Since it gives the derived class access to members of the base class (depending on what language and which kind of inheritance) it is said that it breaks encapsulation. IMHO this is only if you are clinging to encapsulation in the strictest terms. IMHO it is reasonable to say that you are accepting the derived class as an extension of the base and therefore related in some way and not really breaking the encapsulation. Purists will disagree with this.

Take a look at http://www.ccs.neu.edu/research/demeter/papers/context-journal/node17.html and search for "breaks" for an academic explanation.



回答2:

I think from my point of view it breaks in case of addition of new methods in base or super class. If A is a subclass of B, even if A is not modified in any way, a change in B can break A. (This is called the Ripple Effect)

Example: Suppose A overrides all methods in B by first validating input arguments in each method (for security reasons). If a new method is added to B and A is not updated, the new inherited method would introduce a security hole.

To get rid of pitfalls in inheritance, favor or use “Composition” Instead of Inheritance, simple aggregation instead of inheritance , below is an example:

Imagine two classes, Person and Employee. Instead of asking Employee to inherit from Person, you can compose Person inside Employee and forward the requests for Person functionality to the composed class So We still get the benefit of reusing Person class.

Notes:

  • Person class might be abstract class OR

  • Person class might be protected inside the same package as Employee



回答3:

It depends how we design our class.While designing a class We should have the Open-Closed principle in mind .When we are talking about encapsulation we are talking about modification and when we are talking about inheritance we are talking about extending our application then we ,as designers , should choose what we should protect against modification ( using private modifiers in our class ) thus encapsulate our class and what's the open side of our class that is reserved for future extension.(protected membmers).(Think of it as partial concept in .net languages that each class can be separated to different files thus some of them can be extended by the programmer and some others are generated using code generation tools)



回答4:

imagine:

class A {
    void foo(){
        ...
        this.bar();
        ...
    }
    void bar(){
        ...
    }
}

class B extends A {
    //override bar
    void bar(){
        ...
    }
}

class C {
    void bazz(){
        B b = new B();
        // which bar would be called?
        B.foo();
    }
}

As you see in bazz method which bar will be called? the second one the bar in class B will be called. but, what is the problem here? the problem is foo method in class A will not know anything about the override of bar method in class B, Then your invariants may be violated. because foo may expect the only behavior of bar method that is in own class, not something is overridden. This problem is called fragile base-class problem.