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

Java
После прочтения столько исходного кода, как использовать интерфейсы и абстрактные классы?

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

интерфейс

Официальное объяснение интерфейса представляет собой серию методовутверждение, представляет собой набор некоторых функций метода. Затем мы поговорим о характеристиках интерфейса в соответствии с этим предложением.

Во-первых, из приведенного выше предложения видно, что в интерфейсе определен ряд объявлений методов, но нет реализации метода. С этой точки зрения интерфейс является своего рода создателем правил. как вы это реализуете, но только сдерживает вас.Должен иметь эти поведения и соблюдать эти правила. В нашем методе нам нужно определить серию кодов бизнес-логики для выполнения различных конкретных действий.Поэтому метод является формой поведения в системе, а интерфейс ограничивает, какие поведения мы должны иметь.Итак, подведем итог:Интерфейс — это абстракция поведения.

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

<img src="images/加班.jpeg" style="zoom:80%; margin-left:0px;" />

абстрактный класс

Интуитивно абстрактный класс — это абстракция класса, а мы знаем, что класс — это абстракция всех объектов, принадлежащих к одному и тому же классу.Java — это объектно-ориентированный язык программирования, который абстрагирует объективные вещи в реальном мире в объекты. Следовательно, мы знаем, что объект — это абстракция объективных вещей реального мира. Итак, если подытожить одним предложением,Абстрактный класс — это абстракция класса и дальнейшая абстракция объективных вещей в реальном мире.

<img src="images/下载.jpg" style="zoom:100%; margin-left:0px;" />

интерфейс против абстрактного класса

Этот вопрос должен быть часто задаваемым.Автор считает, что мы можем сравнить их с трех точек зрения: (1) класс (2) атрибут (3) метод

С точки зрения класса

  • Чтобы использовать абстрактный класс, класс должен использовать ключевое слово extends, то есть он должен наследовать абстрактный класс, а поскольку в Java используется одиночное наследование, он может наследовать только один абстрактный класс.
  • Чтобы использовать интерфейс, класс должен использовать ключевое слово Implements, которое называется реализацией интерфейса.В то же время, поскольку Java представляет собой механизм множественной реализации, он может реализовывать несколько интерфейсов.
  • И абстрактные классы, и интерфейсы не могут быть созданы, то есть интерфейсы или объекты абстрактного класса не могут быть созданы.

С точки зрения атрибута

Сначала мы смотрим на следующий код

abstract class AbstractClass
{
    private int a;//可以
    int b;//可以
    protected int c;//可以
    public int d;//可以
    private final int e=1;//可以
    private static int f=2;//可以
    private static final int g=3;//可以
}

interface  Interface
{
    private int a=1;//不可以
    int b;//不可以
    int c=1;//可以
    protected int d=2;//不可以;
    public int e=3;//可以
    public  static int f=4;//可以
    public static final int g=5;//可以
}

Из приведенного выше кода мы видим, что

  • Определение атрибутов в абстрактном классе ничем не отличается от определения атрибутов в обычных классах.Как определяются атрибуты определенного класса, так и могут быть определены атрибуты абстрактного класса.
  • В интерфейсе мы можем использовать только модификаторы без каких-либо модификаторов, с public, со static и с final, Фактически, после декомпиляции мы видим, что все свойства в интерфейсе изменены с помощью public static final. То есть свойства, определенные в интерфейсе, существуют в виде констант.

С точки зрения метода

С точки зрения методов самая большая разница между абстрактными классами и интерфейсами должна быть, особенно сейчас, когда каждая версия постоянно меняет методы в интерфейсах.Вот, взяв в качестве примера JDK1.8, сравните методы в интерфейсах и абстрактных классах. различия.

  • Класс с абстрактными методами должен быть абстрактным классом, но абстрактный класс не обязательно должен состоять из всех абстрактных методов, он может иметь и обычные методы, или даже все обычные методы (но как же абстрактного метода нет, и зачем ему быть определены как абстрактный класс?) Для обычных методов в абстрактных классах определяются так же, как и в обычных классах, и могут быть изменены с помощью частных, немодифицированных, защищенных или общедоступных. Для абстрактных методов нельзя использовать частную модификацию (поскольку сами абстрактные методы необходимо переписать путем наследования подклассов). Обычные методы можно изменить с помощью static, но абстрактные методы нельзя изменить с помощью static.
  • Методы в интерфейсе могут быть изменены без модификатора, или их можно модифицировать с помощью публики. После декомпиляции можно увидеть, что методы в интерфейсе изменяются общественным абстрактным, что аналогично свойствам в интерфейсе. Разница в том, что в JDK1.8 интерфейсы могут определять статические методы и методы по умолчанию и должны давать реализации по умолчанию.

Как использовать два вместе

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

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

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

один пример

<img src="images/例子.jpg" style="zoom:80%;" />

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

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

interface Car
{
    //行进
    public void move();

    //补充能量
    public void addEnergy();

    //开门
    public void openTheDoor();

    //关门
    public void closeTheDoor();
}

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

abstract class AbstractFuelCar implements Car
{
    public void move()
    {
        System.out.println("油车突突突的向前冲!!!");
    }
    public void addEnergy()
    {
        System.out.println("加油。。。");
        //调用子类重写的加油方法。
        refuel();
    }
    public void openTheDoor()
    {
        System.out.println("燃油车开门。。。");
    }
    public void closeTheDoor()
    {
        System.out.println("燃油车关门。。。");
    }
    public abstract void refuel();
}

abstract class AbstractEnergyCar implements Car
{
    public void move()
    {
        System.out.println("电车滋滋滋的向前冲!!!");
    }
    public void addEnergy()
    {
        System.out.println("加电。。。");
        //调用子类重写的加油方法。
        charge();
    }
    public void openTheDoor()
    {
        System.out.println("电车开门。。。");
    }
    public void closeTheDoor()
    {
        System.out.println("电车关门。。。");
    }
    public abstract void charge();
}

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

class BMW extends AbstractFuelCar
{

    @Override
    public void refuel()
    {
        System.out.println("BMW加油了!!!!");
    }

    public void someOtherFunction()
    {
        System.out.println("我有点小贵。。。");
    }
}

class Tesla extends  AbstractEnergyCar
{

    @Override
    public void charge()
    {
        System.out.println("特斯拉充电了。。。。");
    }
    public void someOtherFunction()
    {
        System.out.println("俺加速快!!!");
    }
}

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

<img src="images/接口抽象类.png" style="zoom:80%;" />

Обучение в мире Java

Давайте посмотрим, как интерфейсы и абстрактные классы используются вместе в библиотеках классов Java и в некоторых распространенных сторонних платформах с открытым исходным кодом.

1. StringBuilder и StringBuffer

Структура наследования StringBuilder и StringBuffer выглядит следующим образом:

<img src="images/StringBuilder.png" style="zoom: 66%;margin-left:0px;" /><img src="images/StringBuffer.png" style="zoom:65%;margin-left:20px;" />

2. Каркас сбора на Java

ArrayList

<img src="images/ArrayList.png" style="zoom: 50%;margin-left:0px;" />

HashMap

<img src="images/HashMap.png" style="zoom:80%;margin-left:0px;" />

3. Пул потоков ThreadPoolExecutor

<img src="images/ThreadPoolExecutor.png" style="zoom:100%;margin-left:0px;" />

4. Сторонний фреймворк с открытым исходным кодом

Класс реализации BeanFactory в Spring, класс реализации ApplicationContext, BeanPostProcessor, реализация PointCutAdvisor в AOP и т. д., SpringJDBC, управление транзакциями, SpringMVC, SqlSession в MyBatis и т. д. имеют большое количество таких структур, поскольку их структура наследования в целом более сложная. , и не будет прилагаться здесь.На изображении выше заинтересованные студенты могут просмотреть соответствующий исходный код Spring, MyBatis и других фреймворков.