Абстракция – это качество общения с идеями, а не с событиями. Например, в случае с 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;
   }
   // Остаток определения класса
}

Оглавление