Каковы простые для понимания * плохие * примеры использования наследования? - PullRequest
4 голосов
/ 05 августа 2010

Я ищу плохой пример использования наследования.Я не очень креативен, так что это было лучшее, что я мог придумать:

class Car : public Engine {}

У машины есть двигатель, но это не двигатель.

Это, вероятно, сработало бы для объяснения концепции, но я считаю, что есть более наглядные примеры?

Ответы [ 4 ]

5 голосов
/ 05 августа 2010

«Классический» пример; -):

public class Stack extends Vector { 
    ...
}

Стек НЕ является вектором.

Если Stack расширяет Vector, вы можете вставлять / удалять по каждому заданному индексу, тогда как вам разрешается добавлять / удалять элементы только путем нажатия / выталкивания.

4 голосов
/ 05 августа 2010

Используйте практически любой пример, в котором используется наследование без учета поведения базового класса.

Классическим примером являются отношения между Square и 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;
        }
    }
}

Если другому классу Client требуется Rectangle, но он получает Square, Client сломаетсяпотому что он ожидает, что у его Rectangle будут Width и Height, которые не влияют друг на друга.

1 голос
/ 05 августа 2010

Наследование очень полезно, но также нарушает инкапсуляцию. Это означает, что ваши подклассы зависят от деталей реализации суперкласса; если суперкласс изменится, ваш подкласс может сломаться. Вот пример на Java от Effective Java Джоша Блоха:

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);
   }
}

Проблема в том, что метод addAll () в HashSet внутренне использует метод add (), но не документирует это. Так что если вы попробуете

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

в итоге вы получите счет 6 вместо 3. В данном конкретном случае это не очень вредно, но если вы добавляете большую коллекцию или выполняете какую-либо другую операцию, это может быть.

Таким образом, конкретные классы, как правило, не являются хорошей идеей для наследования, если они не предназначены для подклассов.

0 голосов
/ 05 августа 2010

Это обсуждалось годами, и вы найдете много материалов / бесед, касающихся проблемы, в Google.

public class Square extends Rectangle { 
    ...
}

Возможно, это не очень удивительно, но квадрат не должен наследовать от прямоугольника.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...