Я хотел бы знать, в чем проблема с обработкой множественного наследования в java? то есть я работал над чем-то, когда дошел до того, что мне нужно было наследовать несколько абстрактных классов extends
в Java, но я понимаю, что это не разрешено, или, по крайней мере, я пробовал что-то вроде того, что extends CLaseA,ClaseB
я искал какое-то время, и я не нашел что-нибудь, что объясняет, почему это.
так может кто-нибудь помочь мне узнать, почему? Кроме того, поскольку это невозможно сделать , какие у меня есть другие альтернативы?
Короткий ответ
Можно сказать, что в основном существует два типа множественного наследования: множественное наследование реализации класса и множественное наследование реализации типа .
Создатели Java явно запретили первое. Таким образом, любая попытка расширить класс из более чем одного класса приведет к ошибке. Основными причинами для этого были:
Все это будет объяснено более подробно в длинном ответе.
длинный ответ
Все мы знаем, что значит наследовать . Короче говоря, это получение чего-то от кого-то вроде нас и возможность наслаждаться этим.
В ООП наследование означает, что объект получает (наследует) что-то от другого объекта, чтобы использовать его.
Слово, чтобы выразить это в Java,
extends
. Когда класс расширяет более одного класса, это называется множественным наследованием.Например, класс
VehiculoMotor
расширяет классыVehiculoDiesel
иVehiculoGasolina
.Теперь мы можем говорить о двух типах множественного наследования, согласно документации Java : реализация множественного наследования (классов) и реализация множественного наследования типов (с интерфейсами).
1. Множественное наследование реализации (классов)
Реализация множественного наследования — это возможность наследовать определения методов от нескольких классов.
Этот тип наследования невозможен в Java .
Почему Java не поддерживает множественное наследование?
В той же документации (ссылка выше) объясняются некоторые причины:
Конфликты имен и двусмысленность. Когда компиляторы языков программирования, поддерживающие этот тип суперкласса с множественной последовательностью, содержат методы с одинаковыми именами, они иногда не могут определить, к какому члену или методу обращаться или вызывать.
Кроме того, программист может непреднамеренно вызвать конфликт имен, добавив новый метод в суперкласс.
Типичной проблемой, возникающей при реализации множественного наследования, является так называемая проблема алмаза .
Давайте посмотрим изображение:
Эта проблема возникла бы, если бы классы
VehiculoDiesel
иVehiculoGasolina
имели методы с одинаковыми именами. Давайте представим, что у обоих есть методllenar()
. Пока все идеально. Но, поскольку классVehiculoMotor
расширяется из этих двух классов. Если мы сделаем это:Что будем заправлять
camion
, дизель или бензин? Сложный вопрос, не так ли? Мы могли бы разбить грузовик.Это основная причина, по которой реализация множественного наследования невозможна в Java.
2. Реализация множественного наследования с типами
Начиная с Java 8, благодаря введению методов по умолчанию , можно использовать форму реализации множественного наследования с использованием интерфейсов. То есть класс может реализовать (
implements
) более одного интерфейса, который может содержать методы по умолчанию с одинаковыми именами. Компилятор Java предоставляет некоторые правила для определения того, какой метод по умолчанию использует конкретный класс.Язык программирования Java поддерживает множественное наследование типов, то есть способность класса реализовывать более одного интерфейса. Объект может иметь несколько типов: тип собственного класса и типы всех интерфейсов, реализуемых классом. Это означает, что если переменная объявлена как тип интерфейса, то ее значение может ссылаться на любой объект, созданный из любого класса, реализующего интерфейс. Это обсуждается в разделе « Использование интерфейса как типа » документации Java.
Как и в случае множественного наследования реализации, класс может наследовать различные реализации метода, определенного (по умолчанию или статического) в расширяемых им интерфейсах. В этом случае компилятор или пользователь должны решить, какой из них использовать.
Это решает упомянутую выше проблему алмазов , которая была основной причиной предотвращения множественного наследования между классами в языке Java.
Взяв тот же пример с изображения, мы можем
VehiculoMotor
реализовать в классе два интерфейсаLlenableGasolina
иLlenableDiesel
каждый из них с методом по умолчаниюllenar()
.Интерфейс
LlenableDiesel
Интерфейс
LlenableGasolina
Имея два таких интерфейса, мы можем создать класс,
VehiculoMotor
в котором программист может переопределить метод,llenar()
указывающий внутри него, какой из двух методов будет вызываться, используя метод по умолчанию любого из интерфейсов, реализуемых классом. Таким образом, если необходимо вызвать метод, соответствующий дизельным автомобилям:Вместо этого, чтобы вызвать метод
llenar()
для автомобилей с бензиновым двигателем:Вывод этого кода:
Учебный класс
VehiculoMotor
Тогда было бы так:
Подробнее
Тема обсуждалась много лет назад (в 2002 году) в JavaWorld .
Среди причин, по которым Java не допускает множественного наследования, можно назвать:
И говорят, что в качестве решения было выбрано использование нескольких интерфейсов:
В этой статье есть ссылки на другие интересные статьи и обсуждения на эту тему, если вы хотите углубиться.
Чтобы добавить к ответу А. Чедано , есть два дополнительных соображения:
Java поддерживает множественное наследование на уровне интерфейса. Пример:
Начиная с Java 8 возможности интерфейсов были расширены за счет наличия методов по умолчанию, то есть интерфейс может обеспечивать реализацию своих методов. Это означает, что интерфейс/класс, расширяя/реализуя более одного интерфейса, теперь может попасть в проблему алмаза. Компилятор решает эти случаи, требуя от конкретного класса реализации конфликтующего метода. Пример:
Вылет из:
Джеймс Гослинг исключил это при создании java. Он отметил, что множественное наследование не дает больших преимуществ C++ и что его можно лучше реализовать при правильном использовании интерфейсов.
Я действительно не понимаю, в чем проблема? Мне кажется, что решение так же просто, как необходимость указать, из какого родительского класса исходит метод, который мы хотим вызвать, только если он повторяется в других родительских классах. среда разработки Java, .Net, ruby... и любого другого объектно-ориентированного языка должна предупреждать программиста каждый раз, когда этот "конфликт происходит" с прожектором, красным светом или чем угодно, и все! они десятилетиями тонули в чем-то таком глупом, и не похоже, что они захотят снова дышать. множественное наследование очень необходимо и полезно.