Почему множественное наследование не разрешено в Java или C #? - PullRequest
103 голосов
/ 15 июня 2009

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

Ответы [ 17 ]

4 голосов
/ 15 июня 2009

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

3 голосов
/ 05 декабря 2014

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

2 голосов
/ 30 октября 2012

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

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

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

1 голос
/ 06 ноября 2015

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

Причина:

Множественное наследование: Вносит больше сложности и неоднозначности.

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

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

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

  1. Предположим, что есть 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
            }
        }
    
  2. Но через интерфейсы с ключевым словом (реализует) возможно множественное наследование.

    interface A
        {
           // display()
        }
    
    
     interface B
        {
          //display()
        }
    
     class C implements A,B
        {
           //main()
           C object = new C();
           (A)object.display();     // call A's display
    
           (B)object.display(); //call B's display
        }
    }
    
0 голосов
/ 19 августа 2018

В C ++ класс может наследовать (прямо или косвенно) от более чем одного класса, который называется множественное наследование .

C # и Java, однако, ограничивают классы одиночным наследованием каждый класс наследует из одного родительского класса.

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

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

Проблема множественного наследования заключается в том, что оно может привести к неоднозначности. Классический пример - это когда класс наследуется от двух других классов, каждый из которых наследуется от того же класса:

class A {
    protected:
    bool flag;
};
class B : public A {};
class C : public A {};
class D : public B, public C {
    public:
    void setFlag( bool nflag ){
        flag = nflag; // ambiguous
    }
};

В этом примере элемент данных flag определяется как class A. Но class D происходит от class B и class C, которые оба происходят от A, поэтому по сути две копии из flag доступны, потому что экземпляры A находятся в иерархии классов D. Какой из них вы хотите установить? Компилятор будет жаловаться что ссылка на flag в D является неоднозначной . Одним из исправлений является явное устранение неоднозначности ссылки:

B::flag = nflag;

Другим исправлением является объявление B и C как virtual base classes, что означает, что только одна копия A может существуют в иерархии, устраняя любую неопределенность.

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

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

0 голосов
/ 02 января 2017

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

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

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

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

  1. Что если методы или конструкторы из различных суперклассов создают одно и то же поле?

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

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

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

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

См. Этот связанный вопрос SE для дополнительной информации:

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

0 голосов
/ 28 ноября 2016

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

Имеет CalcualteArea метод:

Class Shape1
{

 public void CalculateArea()

     {
       //
     }
}

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

Class Shape2
{

 public void CalculateArea()

     {

     }
}

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

public class Circle: Shape1, Shape2
{
}

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

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

...