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

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

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

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

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

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

как вы написали, «это позволяет мне работать с любым классом, реализующим интерфейс» - больше добавить нечего

user85421 10.06.2024 19:48

Работа с интерфейсами заставляет думать не о поведении, а о общении. Примером может служить интерфейс CRUD, который вы можете использовать сначала HashMap, а затем заменить реализацией, которая фактически подключается к базе данных. Другой момент заключается в том, что замена компонентов (если все сделано правильно, с использованием Фабрик и других шаблонов) позволяет заменять компоненты с небольшими изменениями или вообще без них. Взгляните на класс ServiceLoader, который поможет вам переключаться между компонентами, передавая их как системные свойства.

J.Adler 11.06.2024 02:58

Разве подобные вещи не задавались и не отвечали на них много раз раньше? Где вы показываете свои исследования по этому поводу в своем вопросе?

Hovercraft Full Of Eels 11.06.2024 17:48
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
87
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В приведенном ниже примере list1 или list2 можно использовать в качестве аргумента метода отображения. Если бы вы явно использовали типы классов, это не сработало бы, поскольку вам потребовалось бы два метода: один для ArrayList и один для LinkedList.

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

List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = new LinkedList<>();

public <T> T void display(List<T> list) {
    System.out.printnln(list);
}

Хотя это не имеет отношения к вашему конкретному вопросу, я использовал дженерики, поэтому List<String> list3 также может быть аргументом для display.

Далее следует более fun пример. Обратите внимание, что я могу назначить каждый класс «животное» списку MealTime, поскольку каждый из них реализует этот интерфейс. В противном случае эти классы можно было бы назначить только List<Object>.

interface MealTime {
    public String feedMe();
}

class Lion implements MealTime {
    private String food;

    public Lion(String food) {
        this.food = food;
    }

    public String feedMe() {
        return food;
    }
}

class Koala implements MealTime {
    private String food;

    public Koala(String food) {
        this.food = food;
    }

    public String feedMe() {
        return food;
    }
}



public static void main(String[] args) {
    List<MealTime> zoo = List.of(
            new Koala("Eucalyptus leaves"),
            new Lion("Eland meat"));

   FeedTheAnimals(zoo);
}

public static void FeedTheAnimals(List<MealTime> zoo) {
    for (MealTime animal : zoo) {
        System.out.println("I am feeding the "
                + animal.getClass().getSimpleName() + " some " + 
               animal.feedMe());
    }
}

принты

I am feeding the Koala some Eucalyptus leaves
I am feeding the Lion some Eland meat

Другие вопросы по теме