Когда и где использовать абстрактные классы, а когда и где использовать интерфейсы в Java? - PullRequest
0 голосов
/ 05 ноября 2011

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


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

Оба они никогда не могут быть объявлены как окончательные, очевидно, потому что они должны наследоваться каким-то другим неабстрактным классом (классами).

Оба они никогда не могут иметь статические методы.Ни конкретные, ни абстрактные (абстрактные статические методы на самом деле и на самом деле вообще не существуют).

Интерфейс никогда не может иметь конкретных методов (метод с его фактической реализацией), однако абстрактный класс может иметьконкретные методы тоже.

Интерфейс не может иметь конструкторов, однако абстрактный класс может иметь.


Здесь могут возникнуть два очевидных вопроса.

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

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

Ответы [ 2 ]

2 голосов
/ 05 ноября 2011

Во-первых, вы на самом деле ошибаетесь в нескольких местах:

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

Неправильно. Аннотация и интерфейс могут быть созданы анонимно.

  • Оба они никогда не могут быть объявлены как окончательные, очевидно, потому что они должны наследоваться каким-то другим неабстрактным классом (ами).

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

  • У них обоих никогда не может быть статических методов. Ни конкретные, ни абстрактные (абстрактные статические методы на самом деле вообще не существуют).

Абстрактные классы могут иметь статические методы; извините!

  • Интерфейс никогда не может иметь конкретных методов (метод с его фактической реализацией), однако абстрактный класс также может иметь конкретные методы.

Да, это одно из основных различий между ними.

  • Интерфейс не может иметь конструкторов, однако абстрактный класс может иметь.

Да, это правда.

Теперь перейдем к вашим вопросам:

В вашем первом абзаце нет вопросов. Какой там был вопрос? Если это было «Зачем позволять абстрактным классам иметь конструкторы, если вы не можете их создать?» ответ так, чтобы дочерние классы могли использовать это. Вот пример

abstract class Parent {
    String name;
    int id;
    public Parent(String n, int i) { name = n; id = i; }
}

class Child extends Parent {
    float foo;
    public Child(String n, int i, float f) {
        super(n,i);
        foo = f;
    }
}

// later
Parent p = new Parent("bob",12); // error
Child c = new Child("bob",12); // fine!

Ваш второй абзац имеет вопрос, но имеет неправильный формат Я думаю, что вы просто упускаете «есть» там… :) Ответ на это следующий:

Вы используете интерфейс, когда хотите определить контракт. Вот очень конкретный пример:

public interface Set<E> {
    int size(); // determine size of the set
    boolean isEmpty(); // determine if the set is empty or not
    void add(E data); // add to the set
    boolean remove(E data); // remove from the set
    boolean contains(E data); // determine if set holds something
}

Четыре общих метода для всех наборов.

Вы используете абстрактный класс, когда хотите определить НЕКОТОРЫЕ из поведения, но все еще имеете контракт

public abstract class AbstractSet<E> implements Set<E> {
   // we define the implementation for isEmpty by saying it means
   // size is 0
   public boolean isEmpty() { return this.size() == 0; }
   // let all the other methods be determined by the implementer
}
0 голосов
/ 10 января 2015

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

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

По моему личному опыту, я делаю это, используя подход сверху вниз, а затем снизу вверх. Я начинаю искать наследование, рассматривая сценарий использования и выясняя, какие классы мне понадобятся. Затем я смотрю, есть ли superClassOrInterfaceType (поскольку классы и интерфейсы определяют типы, я объединяю их в одно слово для простоты. Надеюсь, это не делает его более запутанным) объект домена, который будет охватывать все объекты, как в superClassOrInterfaceType транспортного средства, если я работаю над сценарием использования, имеющим дело с subtypeClassOrInterfaceTypes, например: автомобили, грузовики, джипы и мотоциклы, например. Если есть отношение иерархии, то я определяю superClassOrInterfaceType и subtypeClassOrInterfaceTypes.

Как я уже сказал, в первую очередь я ищу общий домен superClassOrInterfaceType для объектов, с которыми я имею дело. Если это так, я ищу общие операции метода между subtypeClassOrInterfaceTypes. Если нет, я посмотрю, есть ли общие реализации методов, потому что, хотя у вас может быть superClassOrInterfaceType и могут быть общие методы, реализации могут не поддерживать повторное использование кода. На данный момент, если у меня есть общие методы, но нет общих реализаций, я склоняюсь к интерфейсу. Однако в этом упрощенном примере у меня должны быть общие методы с некоторыми общими реализациями для транспортного средства subtypeClassOrInterfaceTypes, с которыми я могу повторно использовать код.

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

Как правило, если существует наследование с общими методами и общими реализациями и потребность в нескольких методах реализации подтипа в одном и том же подтипе, то я использую абстрактный класс, что редко, но я его использую. Если вы просто используете абстрактные классы только из-за наследования, вы можете столкнуться с проблемами, если код сильно изменится. Это очень подробно описано в приведенном здесь примере: Интерфейсы против абстрактных классов в Java , для различных типов доменных объектов двигателей. Для одного из них требовался двигатель с двойным питанием, который требовал использования нескольких методов реализации подтипа в одном классе подтипа.

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

Вот несколько ссылок, которые более подробно рассказывают об этом.

Спасибо Тип и Нежный класс

Магия подтипа Полиморфизм

Максимальная гибкость с интерфейсами и абстрактными классами

Интерфейсы против абстрактных классов в Java

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