Абстракция — это качество общения с идеями, а не с событиями. Например, в случае с e-mail, подробные детали о происходящем во время отправки e-mail, используемый протокол сервером e-mail – всё это скрыто от пользователя. Тем не менее, для отправки e-mail вам достаточно напечатать содержимое, адрес получателя и нажать «отправить».
Так и в объектно-ориентированном программировании: абстракция – это процесс скрытия деталей реализации от пользователя, предоставляя ему только функционал. Иными словами, пользователь будет владеть информацией о том, что объект делает, а не как он это делает.
В Java абстракция достигается с использованием абстрактных классов и интерфейсов.
Абстрактный класс
Класс, который во время объявления содержит в себе ключевое слово abstract, известен как абстрактный класс.
- Абстрактные классы в Java могут содержать или не содержать абстрактные методы, т.е. методы без тела (public void get();)
- Если класс имеет хотя бы один абстрактный метод, то класс должен быть объявлен абстрактным.
- Если класс объявлен абстрактным, его нельзя реализовать.
- Чтобы использовать абстрактный класс, вам нужно наследовать его из другого класса, обеспечить реализацию абстрактных методов в нём.
- Если вы наследуете абстрактный класс в Java, вам нужно обеспечить реализацию всех абстрактных методов в нём.
Пример
Эта глава показывает вам пример абстрактного класса. Чтобы создать абстрактный класс, просто используйте ключевое слово abstract перед ключевым словом class во время объявления класса.
/* File name : Employee.java */
public abstract class Employee {
private String name;
private String address;
private int number;
public Employee(String name, String address, int number) {
System.out.println("Собираем данные о работнике");
this.name = name;
this.address = address;
this.number = number;
}
public double computePay() {
System.out.println("Внутри Employee computePay");
return 0.0;
}
public void mailCheck() {
System.out.println("Отправляем чек " + this.name + " " + this.address);
}
public String toString() {
return name + " " + address + " " + number;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
public void setAddress(String newAddress) {
address = newAddress;
}
public int getNumber() {
return number;
}
}
Вы можете наблюдать, что помимо абстрактных методов класс Employee такой же, как и обычный класс в Java. Класс теперь абстрактный, но он всё ещё имеет три поля, семь методов и один конструктор.
Теперь попробуйте создать экземпляр класса Employee следующим образом:
/* File name : AbstractDemo.java */
public class AbstractDemo {
public static void main(String [] args) {
/* Следующие действия неверны и выдадут ошибку */
Employee e = new Employee("Иванов И.И.", "Минск, Беларусь", 43);
System.out.println("\n Вызываем mailCheck, используя ссылку Employee --");
e.mailCheck();
}
}
При попытке компиляции вышеприведённого класса вы получите следующую ошибку:
Employee.java:46: Employee is abstract; cannot be instantiated
Employee e = new Employee("Иванов И.И.", "Минск, Беларусь", 43);
^
1 error
Наследование абстрактного класса
Рассмотрим наследоавние абстрактного класса в Java на примере. Вы можете наследовать класс Employee, как конкретный класс, следующим образом:
Пример
/* File name : Salary.java */
public class Salary extends Employee {
private double salary; // Годовая заработная плата
public Salary(String name, String address, int number, double salary) {
super(name, address, number);
setSalary(salary);
}
public void mailCheck() {
System.out.println("Внутри mailCheck класса Salary ");
System.out.println("Отправляем чек" + getName() + " с зарплатой " + salary);
}
public double getSalary() {
return salary;
}
public void setSalary(double newSalary) {
if(newSalary >= 0.0) {
salary = newSalary;
}
}
public double computePay() {
System.out.println("Вычисляем заработную плату для " + getName());
return salary/52;
}
}
Здесь вы не можете создать экземпляр класса Employee, но вы можете создать экземпляр класса Salary, используя который вы сможете получить доступ ко всем трём полям и семи методам класса Employee, как в примере ниже.
/* File name : AbstractDemo.java */
public class AbstractDemo {
public static void main(String [] args) {
Salary s = new Salary ("Петров П.П.", "Москва, Россия", 3, 3600.00);
Employee e = new Salary ("Смирнов О.И.", "Смоленск, Россия", 2, 2400.00);
System.out.println("Вызываем mailCheck, используя ссылку Salary --");
s.mailCheck();
System.out.println("\n Вызываем mailCheck, используя ссылку Employee --");
e.mailCheck();
}
}
После запуска программы будет выдан такой результат:
Собираем данные о работнике
Собираем данные о работнике
Вызываем mailCheck, используя ссылку Salary ––
Внутри mailCheck класса Salary
Отправляем чек Петров П.П. с зарплатой 3600.0
Вызываем mailCheck, используя ссылку Employee ––
Внутри mailCheck класса Salary
Отправляем чек Смирнов О.И. с зарплатой 2400.0
Абстрактный метод
Если вы хотите, чтобы класс содержал конкретный метод, но вы желаете, чтобы фактическая реализация этого метода определялась дочерними классами, вы можете объявить метод в родительском классе как абстрактный
- Ключевое слово abstract используется для объявления метода абстрактным.
- Вам нужно разместить ключевое слово abstract перед именем метода во время его объявления.
- Абстрактный метод в Java содержит сигнатуру метода, но не содержит тела метода.
- Вместо фигурных скобок у абстрактного метода будет точка с запятой (;) на конце.
Рассмотрим пример абстрактного метода в Java.
Пример
public abstract class Employee {
private String name;
private String address;
private int number;
public abstract double computePay();
// Остаток определения класса
}
Объявление метода абстрактным ведёт к двум последствиям:
- Класс, содержащий его, должен быть объявлен абстрактным.
- Любой класс, наследующий текущий класс, должен либо переопределить абстрактный метод, либо объявить себя абстрактным.
Примечание. В конце концов, класс-потомок должен реализовать абстрактный метод, иначе у вас будет иерархия абстрактных классов, экземпляры которых нельзя будет создать.
Предположим, что класс Salary наследует класс Employee, тогда он должен реализовать метод computePay() , как показано ниже:
/* File name : Salary.java */
public class Salary extends Employee {
private double salary; // Годовая заработная плата
public double computePay() {
System.out.println("Вычисляем заработную плату для " + getName());
return salary/52;
}
// Остаток определения класса
}