Почему делают Абстрактные классы и Интерфейсы?

Хорошо я собирался спросить, что различие всего лишь, ему ответили прежде. Но теперь я спрашиваю, почему они имели эти значения? (Я говорю о Java здесь, я не знаю, относится ли то же к другим языкам),

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

Есть ли некоторое преимущество в неспособности записать тело метода или расшириться многократно, что я не вижу?

8
задан Pontus Gagge 3 March 2010 в 11:29
поделиться

7 ответов

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

Java избегает этого, поддерживая множественное наследование только для интерфейсов. Сигнатуры, объявленные в каждом интерфейсе, гораздо проще комбинировать (Java в основном использует объединение всех методов)

10
ответ дан 5 December 2019 в 07:58
поделиться

Множественное наследование в C ++ приводит к семантической неоднозначности, такой как проблема наследования алмаза . МИ довольно мощный, но имеет сложные последствия.

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

5
ответ дан 5 December 2019 в 07:58
поделиться

Множественное наследование сложнее реализовать на языке (на самом деле в компиляторе), поскольку это может привести к определенным проблемам. Эти вопросы обсуждались здесь ранее: Какова точная проблема с множественным наследованием .

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

3
ответ дан 5 December 2019 в 07:58
поделиться

Рассмотрим этот пример:

public abstract class Engine
{
  public abstract void switchPowerOn();
  public abstract void sprinkleSomeFuel();
  public abstract void ignite();

  public final void start()
  {
    switchPowerOn();
    sprinkleSomeFuel();
    ignite();
  }
}

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

Этот шаблон называется «Метод шаблона формы» и, честно говоря, для меня это единственное разумное использование абстрактных классов в Java.

2
ответ дан 5 December 2019 в 07:58
поделиться

Сделать их одним целым - это путь, по которому пошли ребята из Scala с Traits, который представляет собой интерфейс, который может иметь методы и поддерживает множественное наследование.

Я думаю, что интерфейсы, для меня, чисты в том, что они только определяют требования (проектирование по контракту), в то время как абстрактные классы определяют общее поведение (реализация), так что разные инструменты для разной работы? Возможно, интерфейсы также позволяют более эффективно генерировать код во время компиляции?

1
ответ дан 5 December 2019 в 07:58
поделиться

Другой подход, который вы описываете, - это подход, используемый C ++ (например, миксины). Проблемы, связанные с таким «множественным наследованием», довольно сложны и вызывают критику в C ++.

0
ответ дан 5 December 2019 в 07:58
поделиться

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

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

Абстрактный класс = is-a, Strategy = has-a

Изменить: в отношении множественного наследования, см. Ответ Понта Гагге.

0
ответ дан 5 December 2019 в 07:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: