Что такое абстракция. Когда мы говорим слово “программа”, мы подразумеваем некую сущность, которая решает определённые задачи. Мы опускаем тот факт, что программа состоит из объектов, методов, классов и т.д.
В этом случае мы можем сказать, что программа – это абстракция.
Ранее мы уже обсуждали инкапсуляцию на примере полей класса. Теперь рассмотрим ситуацию, когда мы “прячем” от пользователя саму реализацию определённого функционала. То есть, мы акцентируем внимание на том, какую работу выполняет класс, а не на том, как именно он её выполняет.
В языке программирования 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.