开发者

What are some easy to understand *bad* examples of using inheritance?

I'm looking for bad examples of using inhe开发者_如何学运维ritance. I'm not very creative so this was the best I could think of:

class Car : public Engine {}

A car has an engine, but it is not an engine.

This would probably work to explain the concept, but I believe there are more illustrative examples?


The "classic" example ;-):

public class Stack extends Vector { 
    ...
}

A Stack is NOT a Vector.

If Stack extends Vector, you are able to insert/delete at every given index, whereas you should only be allowed to add/delete elements by pushing/popping.


Use pretty much any example that uses inheritance without regard to the behavior of the base class.

A classic example is the relationship between Square and Rectangle. Sure, in mathematics, a square is a type of a rectangle. However, in software design, a square doesn't behave like a rectangle:

public class Rectangle 
{
    public virtual int Width  { get; set; }
    public virtual int Height { get; set; }
}

public class Square : Rectangle
{
    public override int Width
    {
        get { return base.Width; }
        set
        {
            base.Width = value;
            base.Height = value;
        }
    }

    public override int Height
    {
        get { return base.Height; }
        set
        {
            base.Height= value;
            base.Width = value;
        }
    }
}

If another class, Client, needs a Rectangle but gets a Square, Client will break because it expects its Rectangle to have a Width and Height that don't affect each other.


Inheritance is very useful, but also breaks encapsulation. This means that your subclasses depend on implementation details of the superclass; if the superclass changes, your subclass may break. Here's an example in Java, from Effective Java by Josh Bloch:

public class InstrumentedHashSet<E> extends HashSet<E> {

   // number of attempted element insertions
   private int addCount = 0;

   public int getAddCount() {
      return addCount;
   }

   @Override public boolean addAll<Collection<? extends E> c) {
       addCount += c.size();
       return super.addAll(c);
   }
}

The problem is that HashSet's addAll() method uses its add() method internally, but doesn't document this. So if you try

InstrumentedHashSet<String> s = new InstrumentedHashSet<String>();
s.addAll(Arrays.asList("Snap", "Crackle", "Pop"));

you end up with a count of 6 instead of 3. In this particular case that isn't very harmful, but if you were adding a large collection or doing some other operation, it could be.

So, concrete classes are usually not a good idea to inherit from, unless they were designed to have subclasses.


This have been debated for years, and you'll find a lot of materials/talks referencing the problem on google.

public class Square extends Rectangle { 
    ...
}

Perhaps not very surprising though, a square should not inherit from a rectangle.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜