3

When I read the book Effective Java chapter 4, I met some sentences but I can't think them out :

  1. What is the implementation when designing a class , why subclass will rely on the implementation detail of superclass?
  2. Why will inheritance break encapsulation?
3
  • 7
    Drawbacks of designing a class? That is a strange question that doesn't make much sense. As opposed to what? NOT designing it?
    – JohnFx
    May 26, 2012 at 14:28
  • @JohnFx, I'd assume it means the problems of OOP when compared to procedural or functional approaches. My theory-fu is weak on this one, I know the pain but can't articulate what exactly that pain is. May 26, 2012 at 14:32
  • 2
    The examples in Effective Java are very good. Maybe you could point to one or two of those examples and describe what you are having trouble understanding? Then we can give you better, more specific answers.
    – Jeremy
    May 26, 2012 at 15:56

3 Answers 3

3

Implementation question

This is a nuanced way of looking at the base class and derived classes. The implication is that you should look at what the derived class (aka subclass) inherits as a sort of contract with the base class. What the base class provides, or doesn't provide, affects how the derived classes can be used and how much work goes into them.

So let's use a base class of "Shape" with the property "Name."
I derive a "Square" and a "Circle" from Shape, and I'm able to use their inherited Name field to set the object's name.

So far, so good.

Now we add an "Area" property and a "GetArea()" method to Shape.
We can code GetArea() within Shape because we simply return the Area property.
But how do we make the shapes calculate their area? We can't write Shape.CalcArea() as we haven't given it any knowledge of the shape's dimensions. So we're obligated to write a CalcArea() routine in each of the derived classes so that Shape.GetArea() doesn't fail. (failure == not producing expected results)

There are ways to solve this through overrides, virtuals, abstracts, etc... based upon the language. But the point of the sentence is to make you think through those relationships.

We need to think things through because we now want to use Shape to derive a class "Cone." Cones don't have an area, they have a volume. And now you're into your class design questions of what should the base class implement, and what should the derived classes implement.

Encapsulation

By definition, the derived class can see and access everything that the base class has to offer. In the Shape example, this is a "good thing" and we explicitly want to share everything from the base to the derived class.

But let's say that in Shape v2.0, I need to pre-populate things from a database. So I make Shape derive from a database connection class "DBConn." Now, all of my circles, squares, and cones are database connections as well. Each individual shape has access to all of the database connection information and is potentially now tightly bound to how the DBConn actually works.
So instead of calling Square.myDBConn.Connect(), I can just call Square.Connect(). So if I should ever want to change the implementation of Connect() later on, then I'll need to look at all of the derived shape classes to see what may break with that change.

At it's crux, this is the "Is A ..." vs. "Has A ..." encapsulation question that should always be considered when combining objects.

1
  • 2
    The other problem is that if a Shape is a DBConn, then anything in the program that has a Shape can just use it for general database access. Yay! May 27, 2012 at 12:42
1

A subclass relies in the implementation of its super class because it inherits from it. Anything from the super class that is visible from the subclass becomes a dependency and a potential source for error. If the super class implementation changes, then the subclass may no longer be correct, or even compile. This doesn't mean inheritance is a bad thing, it just means you have to be careful when designing your classes. Explicitly documenting your intentions helps.

2
  • When a subclass inherit a super class , why does it depend on its super class's implementation details.This is what am I considered .I can't grasp the meaning of your first two sentence from your comment ,can you explain it in a more concrete way, or give me a link to another page with examples to describe it. May 27, 2012 at 4:25
  • The subclass depends on the implementation of the superclass because it usually uses (and builds upon) the superclass's code. In fact, anything which uses any class depends upon that class and is vulnerable to breakage if that class changes in a way which doesn't preserve its interface. Inheritance is more prone to this though because as well as public members it can also see protected members of the superclass, so has a wider vulnerability. Jun 8, 2012 at 16:19
1

This is really a comment to your comment, but it was too hard to write as a comment.

When a subclass inherit a super class , why does it depend on its super class's implementation details.This is what am I considered .I can't grasp the meaning of your first two sentence from your comment ,can you explain it in a more concrete way, or give me a link to another page with examples to describe it. –

Lets say you have a class that represents a deck of cards, and it has a method deal() that returns the top card off the deck, and a method shuffle() that shuffles the cards in the deck.

You sublcass it, and override shuffle, say, to make it a more random shuffle then the original class had.

Now, at some point in the future, someone edits the base class, and changes deal(). Originally it would take the card and deal it, and move the card to the bottom of the deck, So that eventually if you kept dealing you would get the card back, and the order would repeat.

But now, the method is changed so that deal will check to see if the card was already returned, and if it was, it will reshuffle automatically, once all the cards were dealt one time.

Your sublcass, will not know about this implementation change, and could exhibit strange behavior. Lets say the shuffle method in your derived class is very slow, 3-4 seconds. Now suddenly when dealing, there is a lag time due to the shuffle. The base class does not show any issues, becuase its shuffle is very fast.

That is what they mean by depends on its super class's implementation details.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.