Почему множественное наследование не разрешено в Java или С#?

Я знаю, что множественное наследование недопустимо в Java и С#. Многие книги просто говорят, что множественное наследование не допускается. Но это может быть реализовано с помощью интерфейсов. Ничего не говорится о том, почему это запрещено. Кто-нибудь может сказать мне, почему это запрещено?

Ответ 1

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

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

Для более интересного и углубленного чтения есть некоторые статьи, доступные в Интернете с интервью с некоторыми из разработчиков языка. Например, для .NET Крис Брумме (который работал в MS на CLR) объяснил причины, по которым они решили не:

  • Различные языки действительно имеют разные ожидания относительно того, как MI работает. Например, как конфликты разрешено и дублируются ли дублирующие базы объединены или избыточны. Прежде чем мы сможем реализовать MI в CLR, мы должны сделать обзор всех языков, рисунок выработать общие концепции и решить как выразить их в языковой нейтральной манере. Мы также должны решить, принадлежит ли МИ CLS, и что это означало бы для языки, которые не хотят этой концепции (предположительно, например, VB.NET). из Конечно, бизнес, в котором мы находимся как общий язык выполнения, но мы не добрались до этого для МИ пока.

  • Число мест, где MI действительно подходит, на самом деле довольно маленький. Во многих случаях несколько Наследование интерфейса может получить работу вместо этого. В других случаях вы можете иметь возможность использовать инкапсуляцию и делегация. Если бы мы добавили немного другая конструкция, например миксинов, на самом деле было бы больше мощный?

  • Наследование множественной реализации вносит много сложностей в реализация. Эта сложность удары, макет, отправка, доступ к полям, сериализация, идентификация сравнения, проверяемости, отражения, дженериков и, возможно, много других мест.

Вы можете прочитать всю статью здесь.

Для Java вы можете прочитать в этой статье:

Причины отказа нескольких наследование с языка Java в основном вытекают из "простого объекта" ориентированной и знакомой "цели. простой язык, создатели Java хотел, чтобы большинство разработчиков может захватывать без обширных обучение. С этой целью они сделать язык похожим на С++ как возможно (знакомый) без переноса над С++ ненужная сложность (просто).

По мнению дизайнеров, несколько наследование вызывает больше проблем и путаница, чем она решает. Так они режут множественное наследование от языка (так же, как они сокращают оператор перегрузки). Широкие Опыт С++ научил их, что множественное наследование просто не стоило головная боль.

Ответ 2

Множественное наследование реализации - это то, что не разрешено.

Проблема заключается в том, что компилятор/среда выполнения не могут понять, что делать, если у вас есть класс Cowboy и Artist, как с реализациями для метода draw(), так и при попытке создать новый тип CowboyArtist. Что происходит, когда вы вызываете метод draw()? Кто-то лежит мертвым на улице, или у вас прекрасная акварель?

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

Ответ 3

Причина: Java очень популярен и легко кодируется из-за его простоты.

Итак, что когда-либо разработчикам Java было сложно и сложно понять для программистов, они пытались избежать этого. Одним из таких свойств является множественное наследование.

  • Они избегали указателей.
  • Они избегали множественного наследования.

Проблема с множественным наследованием: Проблема с алмазами.

Пример:

  • Предположим, что класс A имеет метод fun(). класс B и класс C происходит из класса A.
  • И оба класса B и C переопределяют метод fun().
  • Теперь предположим, что класс D наследует как класс B, так и C. (просто предположение)
  • Создать объект для класса D.
  • D d = новый D();
  • и попытайтесь получить доступ к d.fun(); = > он вызовет класс B fun() или класс C fun()?

Это двусмысленность, существующая в проблеме алмаза.

Невозможно решить эту проблему, но она создает больше путаницы и сложности для программиста при чтении. Это вызывает больше проблем, чем пытается решить.

Примечание. Но любым способом вы всегда можете реализовать множественное наследование косвенно с помощью интерфейсов.

Ответ 4

Потому что Java имеет совершенно другую философию дизайна от С++. (Я не собираюсь обсуждать С# здесь.)

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

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

Кроме того, Java была в значительной степени реакцией от С++ и Smalltalk, наиболее известных языков OO. Существует множество других языков OO (Common Lisp на самом деле был первым стандартизованным), с различными OO-системами, которые лучше справляются с MI.

Не говоря уже о том, что вполне возможно сделать MI в Java, используя интерфейсы, состав и делегирование. Это более явное, чем в С++, и поэтому неудобно использовать, но вы получите то, что вы, скорее всего, поймете на первый взгляд.

Здесь нет правильного ответа. Существуют разные ответы, и лучше для конкретной ситуации зависит от приложений и индивидуальных предпочтений.

Ответ 5

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

Ответ 6

В С++ множественное наследование было основной головной болью при неправильном использовании. Чтобы избежать этих популярных проблем дизайна, несколько интерфейсов "наследование" были вынуждены вместо этого использоваться на современных языках (java, С#).

Ответ 7

Множественное наследование

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

Следовательно, можно считать разумным выбором не включать множественное наследование в язык Java.

Ответ 8

Другая причина заключается в том, что однонаследование делает литье тривиальным, не выдавая инструкций ассемблера (кроме проверки совместимости типов, где это необходимо). Если у вас было множественное наследование, вам нужно выяснить, где в дочернем классе запускается определенный родитель. Таким образом, производительность, безусловно, является перком (хотя и не единственным).

Ответ 9

Я принимаю утверждение, что "множественное наследование не разрешено в Java" с щепоткой соли.

Множественное наследование определяется, когда "Тип" наследуется от более чем одного "Тип". И интерфейсы также классифицируются как типы, которые имеют поведение. Таким образом, Java имеет множественное наследование. Просто, что это безопаснее.

Ответ 10

Динамическая загрузка классов затрудняет реализацию множественного наследования.

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

проблема алмаза с множественным наследованием. У нас есть два класса B и C, наследующие от A. Предположим, что B и C переопределяют унаследованный метод и обеспечивают их собственную реализацию. Теперь D наследует от B и C выполнение множественного наследования. D должен наследовать этот переопределенный метод, jvm не может решить, какой переопределенный метод будет использоваться?

В С++ виртуальные функции используются для обработки, и мы должны делать это явно.

Этого можно избежать, используя интерфейсы, нет тел методов. Интерфейсы не могут быть инстанцированы - они могут быть реализованы только классами или расширены другими интерфейсами.

Ответ 11

В прежние времена (70-е годы), когда компьютерная наука была больше наукой и меньше массового производства, у программистов было время подумать о хорошем дизайне и хорошей реализации, и в результате продукты (программы) были высокого качества (например, TCP/IP-дизайн и реализация). В настоящее время, когда все программируют, и менеджеры меняют спецификации до крайних сроков, тонкие проблемы, подобные тем, которые описаны в ссылке на wikipedia со страницы Стив Хей, трудно отследить; поэтому "множественное наследование" ограничено конструкцией компилятора. Если вам это нравится, вы все равно можете использовать С++... и иметь всю свободу, которую вы хотите:)

Ответ 12

Java имеет концепцию, то есть полиморфизм. Существует два типа полиморфизма в java. Есть перегрузка методов и переопределение метода. Среди них переопределение метода происходит с отношением супер- и подкласса. Если мы создаем объект подкласса и вызываем метод суперкласса, и если подкласс расширяет более одного класса, какой метод суперкласса следует вызывать?

Или, вызывая конструктор суперкласса на super(), какой конструктор суперкласса будет вызван?

Эти решения невозможны с помощью современных функций API Java. поэтому множественное наследование не разрешено в java.

Ответ 13

На самом деле множественное наследование вызовет сложность, если унаследованные классы имеют одинаковую функцию. т.е. у компилятора будет путаница, которую нужно выбрать (проблема с алмазом). Таким образом, в Java эта сложность удалена и дала интерфейс, чтобы получить такую ​​функциональность, как множественное наследование. Мы можем использовать интерфейс

Ответ 14

Множественное наследование не допускается непосредственно в Java, но через интерфейсы разрешено.

Причина:

Множественное наследование: Вводит больше сложности и двусмысленности.

Интерфейсы:. Интерфейсы являются полностью абстрактными классами на Java, которые предоставляют вам единый способ правильно очертить структуру или внутреннюю работу вашей программы от ее общедоступного интерфейса, в результате чего получается большая сумма гибкости и многоразового кода, а также большего контроля над тем, как вы создаете и взаимодействуете с другими классами.

Точнее, они представляют собой специальную конструкцию в Java с дополнительным признаком, позволяющим выполнять несколько видов наследования, то есть классы, которые могут быть вырождены до более чем одного класса.

Давайте рассмотрим простой пример.

  • Предположим, что есть 2 класса суперкласса A и B с одинаковыми именами методов, но с разными функциональными возможностями. Через следующий код с (extends) ключевое слово множественное наследование невозможно.

       public class A                               
         {
           void display()
             {
               System.out.println("Hello 'A' ");
             }
         }
    
       public class B                               
          {
            void display()
              {
                System.out.println("Hello 'B' ");
              }
          }
    
      public class C extends A, B    // which is not possible in java
        {
          public static void main(String args[])
            {
              C object = new C();
              object.display();  // Here there is confusion,which display() to call, method from A class or B class
            }
        }
    
  • Но через интерфейсы возможно (наследование) ключевое слово множественное наследование.

    interface A
        {
           // display()
        }
    
    
     interface B
        {
          //display()
        }
    
     class C implements A,B
        {
           //main()
           C object = new C();
           (A)object.display();     // call A display
    
           (B)object.display(); //call B display
        }
    }
    

Ответ 15

Кто-нибудь может сказать мне, почему это не разрешено?

Вы можете найти ответ из этой документации ссылка

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

Если допускается множественное наследование и когда вы создаете объект, создавая экземпляр этого класса, этот объект наследует поля от всех суперклассов класса. Это вызовет две проблемы.

  • Что делать, если методы или конструкторы из разных суперклассов создают одно и то же поле?

  • Какой метод или конструктор будет иметь приоритет?

Хотя множественное наследование состояния теперь разрешено, все же вы можете реализовать

Множественное наследование типа: способность класса реализовать более одного интерфейса.

Множественное наследование реализации (через методы по умолчанию в интерфейсах): Возможность наследования определений методов из нескольких классов

Обратитесь к этому связанному вопросу SE для получения дополнительной информации:

Неограничиваемая множественность наследования с интерфейсом

Ответ 16

Представьте себе этот пример: У меня есть класс Shape1

Он имеет метод CalcualteArea:

Class Shape1
{

 public void CalculateArea()

     {
       //
     }
}

Существует еще один класс Shape2, который также имеет тот же метод

Class Shape2
{

 public void CalculateArea()

     {

     }
}

Теперь у меня есть дочерний класс Circle, он получается как из Shape1, так и Shape2;

public class Circle: Shape1, Shape2
{
}

Теперь, когда я создаю объект для Circle и вызываю метод, система не знает, какой метод вычисляемой области будет вызываться. Оба имеют одинаковые подписи. Поэтому компилятор запутается. Вот почему несколько наследований не допускаются.

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