Руководство по Java Core. Абстракция.

Что такое абстракция. Когда мы говорим слово “программа”, мы подразумеваем некую сущность, которая решает определённые задачи. Мы опускаем тот факт, что программа состоит из объектов, методов, классов и т.д.

В этом случае мы можем сказать, что программа – это абстракция.

Ранее мы уже обсуждали инкапсуляцию на примере полей класса. Теперь рассмотрим ситуацию, когда мы “прячем” от пользователя саму реализацию определённого функционала. То есть, мы акцентируем внимание на том, какую работу выполняет класс, а не на том, как именно он её выполняет.

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


Абстрактные классы

Абстрактным называют класс, который не может иметь экземпляров. Также, он может содержать абстрактные методы (методы без реализации). Для того чтобы сделать класс абстрактным, необходимо применить ключевое слово abstract. Вот некоторые данные об абстрактных классах:

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

Для понимания того, как это работает на практике, рассмотрим пример простого приложения.

Пример:
Абстрактный класс Profession


public abstract class Profession {
    String professionName;
    String industry;

    public Profession(String professionName, String industry) {
        this.professionName = professionName;
        this.industry = industry;
    }

    public String getProfessionName() {
        return professionName;
    }

    public void setProfessionName(String professionName) {
        this.professionName = professionName;
    }

    public String getIndustry() {
        return industry;
    }

    public void setIndustry(String industry) {
        this.industry = industry;
    }

    public abstract void doJob();

    @Override
    public String toString() {
        return "Profession Info:" +
                "\nProfession Name: " + professionName +
                "\nIndustry: " + industry + "\n";
    }
}

Класс Developer


public class Developer extends Profession{
    private String specialty;

    public Developer(String professionName, String industry, String specialty) {
        super(professionName, industry);
        this.specialty = specialty;
    }

    public String getSpecialty() {
        return specialty;
    }

    public void setSpecialty(String specialty) {
        this.specialty = specialty;
    }

    @Override
    public void doJob() {
        System.out.println("Developer writes code...");
    }

    @Override
    public String toString() {
        return "Developer Info" +
                "\nProfession Name: " + this.getProfessionName() +
                "\nIndustry: " + this.getIndustry() +
                "\nSpecialty: " + specialty;
    }
}

Класс Pilot


public class Pilot extends Profession{
    private String aircraftType;

    public Pilot(String professionName, String industry, String aircraftType) {
        super(professionName, industry);
        this.aircraftType = aircraftType;
    }

    public String getAircraftType() {
        return aircraftType;
    }

    public void setAircraftType(String aircraftType) {
        this.aircraftType = aircraftType;
    }

    @Override
    public void doJob() {
        System.out.println("Pilot controls " + this.aircraftType);
    }

    @Override
    public String toString() {
        return "Pilot Info" +
                "\nProfession Name: " + this.getProfessionName() +
                "\nIndustry: " + this.getIndustry() +
                "\nAircraft type: " + aircraftType;
    }
}

Класс ProfessionDemo


public class ProfessionDemo {
    public static void main(String[] args) {
        Developer developer = new Developer("Developer", "IT", "Java");
        Pilot pilot = new Pilot("Pilot", "Aviation", "Boeing 737-800");
        Profession cppDeveloper = new Developer("Developer", "IT", "C++");

        System.out.println(developer);
        System.out.println("=======================");
        System.out.println(pilot);
        System.out.println("=======================");
        System.out.println(cppDeveloper);
    }
}

В результате работы программы мы получим, примерно следующий результат:


/*Some system messages*/

Developer Info
Profession Name: Developer
Industry: IT
Specialty: Java
=======================
Pilot Info
Profession Name: Pilot
Industry: Aviation
Aircraft type: Boeing 737-800
=======================
Developer Info
Profession Name: Developer
Industry: IT
Specialty: C++

Как видите мы можем применять такую форму создания экземпляра класса Developer, как


Profession developer = new Developer(...);

На этом мы завершим обзор абстрактных классов и методов и перейдём к интерфейсам.


Интерфейсы

Интерфейс – это ссылочный тип данных в языке программирования Java. Грубо говоря, интерфейс – это набор абстрактных методов.
Классы, которые имплементируют интерфейсы (реализовывают) наследуют все методы интерфейса и должны их реализовать.
Написание интерфейса аналогично написанию класса, отличие заключается в том, что интерфейс описывает только поведение объекта, которое должно быть реализовано классом.
Вот некоторые свойства интерфейса:

  • Интерфейс может иметь любое количество методов.
  • Интерфейс не может иметь экземпляра.
  • Интерфейс не имеет конструктора.
  • Все методы интерфейса абстрактные.
  • Все поля интерфейса должны иметь модификаторы static и final.
  • Классы именно имплементируют (реализовывают) интерфейсы, а не наследуют.
  • Класс может имплементировать несколько интерфейсов.

Для понимания того, как это работает на практике рассмотрим пример простого приложения.

Пример:

В этом примере у нас есть интерфейсы Developer и Human, которые имеют свои методы. И два класса – JavaDeveloper и CppDeveloper, каждый из которых имплементируют оба интерфейса.

Интерфейс Developer


public interface Developer {
    public void writeCode();

    public void enjoyLife();
}

Интерфейс Human


public interface Human {
    public void breath();
}

Класс JavaDeveloper


public class JavaDeveloper implements Developer, Human {
    private String name;

    public JavaDeveloper(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void writeCode() {
        System.out.println("Java developer writes Java Code...");
    }

    @Override
    public void enjoyLife() {
        System.out.println("Java developer enjoys life...");
    }

    @Override
    public void breath() {
        System.out.println("Breathing like a human...");
    }

    @Override
    public String toString() {
        return "Java Developer" +
                "\nName: " + name + "\n";
    }
}

Класс CppDeveloper


public class CppDeveloper implements Developer, Human {
    private String name;

    public CppDeveloper(String name) {
        this.name = name;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void writeCode() {
        System.out.println("C++ Developer writes C++ code...");
    }

    @Override
    public void enjoyLife() {
        System.out.println("C++ Developer does not have time to enjoy life, he learn C++ all time...");
    }

    @Override
    public void breath() {
        System.out.println("Breathing like a human...");
    }


    @Override
    public String toString() {
        return "C++ Developer" +
                "\nName: " + name + "\n";
    }
}

Класс DeveloperRunner


public class DeveloperRunner {
    public static void main(String[] args) {
        JavaDeveloper javaDeveloper = new JavaDeveloper("Java Man");
        CppDeveloper cppDeveloper = new CppDeveloper("Cpp Hero");

        System.out.println("Developers Info:");
        System.out.println(javaDeveloper);
        System.out.println(cppDeveloper);

        System.out.println("Java Developer's methods: ");
        javaDeveloper.breath();
        javaDeveloper.writeCode();
        javaDeveloper.enjoyLife();

        System.out.println("\n==============\n");

        System.out.println("C++ Developer's methods: ");
        cppDeveloper.breath();
        cppDeveloper.writeCode();
        cppDeveloper.enjoyLife();
    }
}

В результате работы программы мы получим следующий результат:


Developers Info:
Java Developer
Name: Java Man

C++ Developer
Name: Cpp Hero

Java Developer's methods: 
Breathing like a human...
Java developer writes Java Code...
Java developer enjoys life...

==============

C++ Developer's methods: 
Breathing like a human...
C++ Developer writes C++ code...
C++ Developer does not have time to enjoy life, he learn C++ all time...

Существует ряд правил реализации интерфейсов:

  • Класс может имплементировать более любое количество интерфейсов.
  • Интерфейс может наследовать другой интерфейс (по аналогии с классами).

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

Рассмотрим следующий пример.

Пример:
У нас есть интерфейс Job, который имеет один метод doJob(). Другой интерфейс – ProductManagement наследует этот интерфейс и добавляет свой собственный getPowerOverDevelopers().

Класс ProductManager, который имплементирует интерфейс ProductManagement, должен реализовывать все методы этих классов.

Интерфейс Job


public interface Job {
    public void doJob();
}

Интерфейс ProductManagement


public interface ProductManagement extends Job{
    public void getPowerOverDevelopers();
}

Класс ProductManager


public class ProductManager implements ProductManagement {
    private String name;

    public ProductManager(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void getPowerOverDevelopers() {
        System.out.println("Product Manger responsible for bonuses...");
    }

    @Override
    public void doJob() {
        System.out.println("Product manager controls everything...");
    }

    @Override
    public String toString() {
        return "Product Manager: " +
                "\nName: " + name + "\n";
    }
}

Класс ProductManagerRunner


public class ProductManagerRunner {
    public static void main(String[] args) {
        ProductManager productManager = new ProductManager("Number One");

        System.out.println("Product Manager Info");
        System.out.println(productManager);

        System.out.println("Product Manager's methods:");
        productManager.doJob();
        productManager.getPowerOverDevelopers();
    }
}

В результате работы программы мы получим следующий результат:


/*Some system messages*/

Product Manager Info
Product Manager: 
Name: Number One

Product Manager's methods:
Product manager controls everything...
Product Manger responsible for bonuses...

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

В следующем уроке мы рассмотрим структуры данных в языке Java.