Как интерфейсы Java имитируют множественное наследование? - PullRequest
73 голосов
/ 24 августа 2010

Я читаю "Учебник по Java" (второй раз).Я только что прошел раздел об интерфейсах (снова), но все еще не понимаю, как интерфейсы Java имитируют множественное наследование.Есть ли более четкое объяснение, чем то, что в книге?

Ответы [ 21 ]

2 голосов
/ 27 марта 2014

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

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

Например:

interface Herbivore {
    void munch(Vegetable v);
};

interface Carnivore {
    void devour(Prey p);
}

interface AllEater : public Herbivore, Carnivore { };

class Fox implements AllEater {
   ... 
};

class Bear implements AllEater {
   ...
};

В этом примере Fox и Bear не могут совместно использовать общую базовую реализацию для своих методов интерфейса munch и devour.

Если базовые реализации выглядят так, мы, возможно, захотим использовать их для Fox и Bear:

class ForestHerbivore implements Herbivore
    void munch(Vegetable v) { ... }
};

class ForestCarnivore implements Carnivore
    void devour(Prey p) { ... }
};

Но мы не можем наследовать оба из них. Базовые реализации должны быть переменными-членами в классе, и определенные методы могут пересылать к этому. То есть:

class Fox implements AllEater {
    private ForestHerbivore m_herbivore;
    private ForestCarnivore m_carnivore;

    void munch(Vegetable v) { m_herbivore.munch(v); }
    void devour(Prey p) { m_carnivore.devour(p); }
}

Это становится громоздким, если интерфейсы растут (то есть более 5-10 методов ...)

Лучший подход - определить интерфейс как совокупность интерфейсов:

interface AllEater {
    Herbivore asHerbivore();
    Carnivore asCarnivore();
}

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

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

2 голосов
/ 24 августа 2010

Нечестно сказать, что интерфейсы «имитируют» множественное наследование.

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

Как правило, смотрите на композицию, где, по вашему мнению, может потребоваться множественное наследование.

ИЛИ Потенциальным решением для достижения чего-то типа множественного наследования является интерфейс Mixin - http://csis.pace.edu/~bergin/patterns/multipleinheritance.html. Используйте с осторожностью!

2 голосов
/ 11 декабря 2012

На самом деле вы можете «наследовать» от нескольких конкретных классов, если они сами реализуют интерфейсы.innerclasses поможет вам достичь этого:

</p> <pre><code>interface IBird { public void layEgg(); } interface IMammal { public void giveMilk(); } class Bird implements IBird{ public void layEgg() { System.out.println("Laying eggs..."); } } class Mammal implements IMammal { public void giveMilk() { System.out.println("Giving milk..."); } } class Platypus implements IMammal, IBird { private class LayingEggAnimal extends Bird {} private class GivingMilkAnimal extends Mammal {} private LayingEggAnimal layingEggAnimal = new LayingEggAnimal(); private GivingMilkAnimal givingMilkAnimal = new GivingMilkAnimal(); @Override public void layEgg() { layingEggAnimal.layEgg(); } @Override public void giveMilk() { givingMilkAnimal.giveMilk(); } }

2 голосов
/ 24 августа 2010

Они этого не делают.

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

Что вы наследуете, реализуя интерфейс?Bubkes!Поэтому, на мой взгляд, прекратите использовать слова интерфейс и наследование в одном предложении.Как сказал Майкл Боргвардт, интерфейс - это не определение, а аспект.

1 голос
/ 09 апреля 2017

Я также должен сказать, что Java не поддерживает множественное наследование.

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

Если вы реализуете интерфейс, существует нулевая вероятность того, что вы пропустите реализацию всех методов в каждом интерфейсе (Исключение: реализации по умолчанию методов интерфейса, представленные в Java 8). Итак, теперь вы полностью осведомлены о происходящем с вещами, которые вы вложили в свой новый класс.

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

Если вам нужна дополнительная информация об интерфейсах Java, ознакомьтесь с этой статьей, http://www.geek -programmer.com / Введение-в-Java-интерфейсы /

1 голос
/ 21 июля 2016

Нет, Java не поддерживает множественное наследование.Ни используя класс, ни используя интерфейс.Обратитесь по этой ссылке для получения дополнительной информации https://devsuyed.wordpress.com/2016/07/21/does-java-support-multiple-inheritance

1 голос
/ 18 мая 2013

В java нет поддержки множественного наследования.

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

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

1 голос
/ 20 февраля 2013

В некоторых случаях множественное наследование оказывается очень удобным и трудным для замены интерфейсами без написания большего количества кода. Например, есть приложения для Android, которые используют классы, полученные из Activity, и другие из FragmentActivity в том же приложении. Если у вас есть особенность, которую вы хотите использовать в общем классе, в Java вам придется дублировать код, а не позволять дочерним классам Activity и FragmentsActivity наследоваться от одного и того же класса SharedFeature. И плохая реализация обобщений в Java тоже не помогает, потому что написание следующего недопустимо:

public class SharedFeature<T> extends <T extends Activity>

...
...
1 голос
/ 24 августа 2010

Я не думаю, что они делают.

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

Я полагаю, что где-то здесь есть вопрос о роли интерфейсов и множественного наследования, но я не могу найти его сейчас ...

1 голос
/ 24 августа 2010

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

...