недостатки наследования в Java - PullRequest
6 голосов
/ 30 июня 2010

Может кто-нибудь объяснить недостаток наследования в Java

Ответы [ 5 ]

10 голосов
/ 30 июня 2010

вы, вероятно, захотите прочесть:

Effective Java ™, второе издание. Автор: Джошуа Блох

Глава 4. Классы и интерфейсы

Элемент 16. Композиция Favour по наследованию

Пункт 17: Дизайн и документация для наследования или иного запрета

Пункт 18: Предпочитать интерфейсы абстрактным классам

5 голосов
/ 30 июня 2010

Посмотрите на статью Аллена Холуба в JavaWorld, озаглавленную Почему расширение - это зло .Он обсуждает такие вещи, как жесткая связь и проблема хрупкого базового класса .

3 голосов
/ 30 июня 2010

Если ваш класс не предназначен для наследования, он должен быть окончательным. Вы должны быть очень осторожны, чтобы убедиться, что вы понимаете, как методы, которые будут переопределены в подклассе, который не был разработан для функции наследования, чтобы понять, как их изменить.

Конкретный пример:

Предположим, у вас есть класс, который управляет списком имен ...

public class MyNameManager {
  private List<String> numbers = new LinkedList<String>();

  public void add(String value) {
    numbers.add(value);
  }

  public void addAll(Collection<String> values) {
    for(String value : values) {
      add(value);
    }
  }

  public void remove(String value) { //... }

  //...
}

Теперь предположим, что вы хотите создать новый подкласс, который также подсчитывает общее количество раз, когда имя добавляется в список, например:

public class MyCountingNameManager extends MyNameManager {
  private int count = 0;

  @Override
  protected void addAll(Collection<String> values) {
    count += values.size();
    super.addAll(values);
  }

  @Override
  protected void add(String value) {
    count += 1;
    super.add(value);
  }
}

Кажется, довольно просто, нет? Но рассмотрим результат следующего:

MyCountingNameManager m = new MyCountingNameManager();
m.add("bob");
m.add("Sally");

Количество теперь 2, и все хорошо. Но если бы мы сделали следующее:

List<String> family = new List<String>();
family.add("mom");
family.add("dad");
family.add("brother");

MyCountingNameManager m = new MyCountingNameManager();
m.add(family);

Счет теперь 6, , а не 3, который вы, вероятно, ожидаете. Это связано с тем, что вызов addAll добавляет размер коллекции значений (которая равна 3) к счетчику, а затем вызывает метод super.addAll для выполнения фактической обработки. super.addAll повторяет коллекцию и вызывает метод add для каждого значения. Но поскольку мы работаем с MyCountingNameManager и , а не a MyNameManager, переопределенный метод add в подклассе вызывается каждый раз. Метод MyCountingNameManager.add, который выполняется, также увеличивает счет! Таким образом, в результате каждое имя считается дважды!

Я полагаю, что этот пример взят из Effective Java. Вы должны обязательно найти копию и прочитать пункты, перечисленные в ответе Viele, чтобы глубже понять некоторые случаи, когда наследование плохо подходит.

2 голосов
/ 30 июня 2010

Мы предпочитаем композицию, а не наследование, потому что когда мы добавляем (в частности) или изменяем функциональность путем создания подклассов, мы связываем эти новые функциональные возможности с классом - поэтому, где бы нам ни понадобилась новая функциональность, нам нужен этот класс.Это распространяется даже на дальнейшие подклассы - и с моделью одиночного наследования Java, если у нас есть два новых бита функциональности, которые мы хотим в еще одном классе, нет (простого) способа ввести оба бита, если каждый находится в отдельном подклассеисходный предок.

Для сравнения, если мы расширяем функциональность с помощью композиции, любой класс - внутри или вне нашей существующей иерархии - может включить его, просто включив крошечный класс, который имеет новую функцию.Он проще, чище, более пригоден для повторного использования и легче для чтения.

Наследование имеет свое место, но оно не подходит для многих, многих заданий.

0 голосов
/ 09 июля 2019

Наследование дает тесную взаимосвязь между классами и имеет большой вес по сравнению с интерфейсами для полиморфизма во время выполнения.

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