Почему в Java нет множественного наследования, но допускается реализация нескольких интерфейсов?

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

Ответы

Ответ 1

Поскольку интерфейсы определяют только то, что делает класс, а не то, как он это делает.

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

Ответ 2

Один из моих преподавателей колледжа объяснил мне это следующим образом:

Предположим, что у меня есть один класс, который является тостером, а другой класс - NuclearBomb. У них обоих может быть "темнота". Оба они имеют метод on(). (У одного есть off(), а другой нет.) Если я хочу создать класс, который является подклассом обоих из них... как вы можете видеть, это проблема, которая может действительно взорваться на моем лице здесь.

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

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

Ответ 3

Поскольку наследование используется слишком часто, даже если вы не можете сказать "эй, этот метод выглядит полезным, я также расширю этот класс".

public class MyGodClass extends AppDomainObject, HttpServlet, MouseAdapter, 
             AbstractTableModel, AbstractListModel, AbstractList, AbstractMap, ...

Ответ 4

Ответ на этот вопрос заключается во внутренней работе компилятора Java (цепочки конструктора). Если мы видим внутреннюю работу компилятора Java:

public class Bank {
  public void printBankBalance(){
    System.out.println("10k");
  }
}
class SBI extends Bank{
 public void printBankBalance(){
    System.out.println("20k");
  }
}

После компиляции это выглядит так:

public class Bank {
  public Bank(){
   super();
  }
  public void printBankBalance(){
    System.out.println("10k");
  }
}
class SBI extends Bank {
 SBI(){
   super();
 }
 public void printBankBalance(){
    System.out.println("20k");
  }
}

когда мы расширяем класс и создаем его объект, одна цепочка конструктора будет работать до класса Object.

Выше код будет работать нормально. но если у нас есть другой класс с именем Car который расширяет Bank и один гибридный (множественное наследование) класс с именем SBICar:

class Car extends Bank {
  Car() {
    super();
  }
  public void run(){
    System.out.println("99Km/h");
  }
}
class SBICar extends Bank, Car {
  SBICar() {
    super(); //NOTE: compile time ambiguity.
  }
  public void run() {
    System.out.println("99Km/h");
  }
  public void printBankBalance(){
    System.out.println("20k");
  }
}

В этом случае (SBICar) не удастся создать цепочку конструктора (неоднозначность времени компиляции).

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

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

Надеюсь, что это решит ваш запрос. Благодарю.

Ответ 5

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

Ответ 6

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

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

В белой статье под названием "Java: обзор" Джеймса Гослинга в феврале 1995 года (ссылка) дает представление о том, почему множественное наследование не поддерживается в Java.

Согласно Гослинг:

"JAVA пропускает много редко используемых, плохо понятых, запутывающих черт С++, которые в нашем опыте приносят больше горя, чем пользы. Эта прежде всего состоит из перегрузки оператора (хотя он имеет перегрузка метода), множественное наследование и расширенная автоматическая" приведения типов.

Ответ 7

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

Урок, извлеченный из С++ w/multiple inheritence, состоял в том, что это привело к большему количеству проблем, чем это было важно.

Интерфейс - это договор вещей, который должен реализовать ваш класс. Вы не получаете никакой функциональности от интерфейса. Наследование позволяет наследовать функциональность родительского класса (и в множественном наследовании, которое может стать чрезвычайно запутанным).

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

Ответ 8

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

  • Множественное наследование состояния: Возможность наследования полей из нескольких классов

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

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

    • Что делать, если методы или конструкторы из разных суперклассов создают одно и то же поле?
    • Какой метод или конструктор будет иметь приоритет?
  • Множественное наследование реализации: Возможность наследования определений методов из нескольких классов

    Проблемы с этим подходом: конфликты имен и двусмысленность. Если подкласс и суперкласс содержат одно и то же имя метода (и подпись), компилятор не может определить, какую версию вызывать.

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

    Для получения более подробной информации о решении проблемы с алмазами см. ниже сообщение SE.

    В чем различия между абстрактными классами и интерфейсами в Java 8?

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

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

Ответ 10

Поскольку этот вопрос не близок, я опубликую этот ответ, надеюсь, это поможет кому-то понять, почему Java не разрешает множественное наследование.

Рассмотрим следующий класс:

public class Abc{

    public void doSomething(){

    }

}

В этом случае класс Abc не делает ничего правильного? Не так быстро, этот класс неявно расширяет класс Object, базовый класс, который позволяет все работать в java. Все это объект.

Если вы попытаетесь использовать класс выше, вы увидите, что ваша среда IDE позволяет использовать такие методы, как: equals(Object o), toString() и т.д., но вы не объявили эти методы, они пришли из базового класса Object

Вы можете попробовать:

public class Abc extends String{

    public void doSomething(){

    }

}

Это хорошо, потому что ваш класс не будет имплицировать extends Object, но будет расширять String, потому что вы это сказали. Рассмотрим следующее изменение:

public class Abc{

    public void doSomething(){

    }

    @Override
    public String toString(){
        return "hello";
    }

}

Теперь ваш класс всегда будет возвращать "привет", если вы вызываете toString().

Теперь представьте себе следующий класс:

public class Flyer{

    public void makeFly(){

    }

}

public class Bird extends Abc, Flyer{

    public void doAnotherThing(){

    }

}

Снова класс Flyer неявный расширяет Object, у которого есть метод toString(), любой класс будет иметь этот метод, поскольку все они косвенно распространяются Object, поэтому, если вы вызываете toString() из Bird, который toString() java придется использовать? Из Abc или Flyer? Это произойдет с любым классом, который пытается расширить два или более классов, чтобы избежать такого "столкновения методов", они построили идею интерфейса, в основном вы могли бы считать их абстрактным классом который не распространяется косвенным образом Объектом. Так как они абстрактные, они должны быть реализованы классом, который является объектом (вы не можете инициировать только интерфейс, они должны быть реализованы классом), поэтому все будет работать нормально.

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

Вы можете реализовать любой интерфейс, который вам нравится в том же классе, поскольку по умолчанию он ничего не расширяет (но вы можете создать интерфейс, который расширяет другой интерфейс, но опять же, интерфейс "отец" не расширяет Object "), поэтому интерфейс - это просто интерфейс, и они не будут страдать от" подписи подписи методов", если они делают компилятор, выдаст вам предупреждение, и вам просто нужно будет изменить подпись метода для его исправления ( signature = имя метода + params + возвращаемый тип).

public interface Flyer{

    public void makeFly(); // <- method without implementation

}

public class Bird extends Abc implements Flyer{

    public void doAnotherThing(){

    }

    @Override
    public void makeFly(){ // <- implementation of Flyer interface

    }

    // Flyer does not have toString() method or any method from class Object, 
    // no method signature collision will happen here

}

Ответ 11

Потому что интерфейс - это просто контракт. И класс на самом деле является контейнером для данных.

Ответ 12

Например, два класса A, B, имеющие один и тот же метод m1(). И класс C расширяет как A, B.

 class C extends A, B // for explaining purpose.

Теперь класс C будет искать определение m1. Во-первых, он будет искать в классе, если он не нашел, тогда он будет проверять в классе родителей. Оба A, B имеют определение. Итак, здесь возникает неопределенность, какое определение следует выбрать. Так что JAVA НЕ ПОДДЕРЖИВАЕТ МНОГОКРАТНОЕ НАСЛЕДОВАНИЕ.

Ответ 13

Java не поддерживает множественное наследование по двум причинам:

  1. В Java каждый класс является потомком класса Object. Когда он наследует от более чем одного суперкласса, подкласс получает неоднозначность приобрести свойство класса объекта.
  2. В Java каждый класс имеет конструктор, если мы пишем его явно или нет вообще. Первое утверждение вызывает super() для вызова конструктор класса ужина. Если в классе более одного суперкласса, запутался.

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

Ответ 14

Возьмем, к примеру, случай, когда класс А имеет метод getSomething и класс B, имеет метод getSomething, а класс C расширяет A и B. Что произойдет, если кто-то вызовет C.getSomething? Невозможно определить, какой метод вызывать.

Интерфейсы в основном просто определяют, какие методы должен содержать класс реализации. Класс, который реализует несколько интерфейсов, просто означает, что класс должен реализовывать методы из всех этих интерфейсов. Что бы не приводило к каким-либо проблемам, как описано выше.

Ответ 15

Рассмотрим сценарий, в котором Test1, Test2 и Test3 являются тремя классами. Класс Test3 наследует классы Test2 и Test1. Если классы Test1 и Test2 имеют один и тот же метод, и вы вызываете его из объекта дочернего класса, будет неоднозначно вызывать метод Test1 или Test2, но нет такой двусмысленности для интерфейса, как в интерфейсе, реализация не существует.

Ответ 16

Java не поддерживает множественное наследование, многолучевое распространение и гибридное наследование из-за двусмысленности Проблема:

 Scenario for multiple inheritance: Let us take class A , class B , class C. class A has alphabet(); method , class B has also alphabet(); method. Now class C extends A, B and we are creating object to the subclass i.e., class C , so  C ob = new C(); Then if you want call those methods ob.alphabet(); which class method takes ? is class A method or class B method ?  So in the JVM level ambiguity problem occurred. Thus Java does not support multiple inheritance.

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

Ссылка ссылки: https://plus.google.com/u/0/communities/102217496457095083679

Ответ 17

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

Ответ 18

* Это простой ответ, так как я новичок в Java *

Рассмотрим три класса X, Y и Z

Таким образом, мы наследуем, как X extends Y, Z И у Y и у Z есть метод alphabet() с тем же типом возврата и аргументами. Этот метод alphabet() в Y говорит об отображении первого алфавита, а метод method в Z говорит об отображении последнего алфавита. Таким образом, здесь возникает двусмысленность, когда alphabet() вызывается X Говорит ли он отображать первый или последний алфавит??? Так что Java не поддерживает множественное наследование. В случае интерфейсов, рассмотрите Y и Z как интерфейсы. Таким образом, оба будут содержать объявление метода alphabet() но не определение. Он не скажет, отображать ли первый алфавит или последний алфавит или что-то еще, но просто объявит метод alphabet(). Так что нет причин поднимать неопределенность. Мы можем определить метод с чем угодно внутри класса X

Таким образом, одним словом, в Интерфейсах определение делается после реализации, поэтому нет путаницы.