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.
精彩评论