Java - Abstração

De acordo com o dicionário, abstractioné a qualidade de lidar com ideias e não com eventos. Por exemplo, quando você considera o caso do e-mail, detalhes complexos, como o que acontece assim que você envia um e-mail, o protocolo que seu servidor de e-mail usa são ocultados do usuário. Portanto, para enviar um e-mail basta digitar o conteúdo, citar o endereço do destinatário e clicar em enviar.

Da mesma forma na programação orientada a objetos, abstração é um processo de ocultar os detalhes de implementação do usuário, apenas a funcionalidade será fornecida ao usuário. Em outras palavras, o usuário terá as informações sobre o que o objeto faz ao invés de como o faz.

Em Java, a abstração é obtida usando classes e interfaces abstratas.

Classe Abstrata

Uma classe que contém o abstract palavra-chave em sua declaração é conhecida como classe abstrata.

  • As classes abstratas podem ou não conter métodos abstratos , ou seja, métodos sem corpo (public void get ();)

  • Mas, se uma classe tem pelo menos um método abstrato, então a classe must ser declarado abstrato.

  • Se uma classe for declarada abstrata, ela não pode ser instanciada.

  • Para usar uma classe abstrata, você deve herdá-la de outra classe, fornecer implementações para os métodos abstratos nela.

  • Se você herdar uma classe abstrata, terá que fornecer implementações para todos os métodos abstratos nela.

Exemplo

Esta seção fornece um exemplo da classe abstrata. Para criar uma classe abstrata, basta usar oabstract palavra-chave antes da palavra-chave class, na declaração de classe.

/* 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("Constructing an Employee");
      this.name = name;
      this.address = address;
      this.number = number;
   }
   
   public double computePay() {
     System.out.println("Inside Employee computePay");
     return 0.0;
   }
   
   public void mailCheck() {
      System.out.println("Mailing a check to " + 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;
   }
}

Você pode observar que, exceto os métodos abstratos, a classe Employee é igual à classe normal em Java. A classe agora é abstrata, mas ainda tem três campos, sete métodos e um construtor.

Agora você pode tentar instanciar a classe Employee da seguinte maneira -

/* File name : AbstractDemo.java */
public class AbstractDemo {

   public static void main(String [] args) {
      /* Following is not allowed and would raise error */
      Employee e = new Employee("George W.", "Houston, TX", 43);
      System.out.println("\n Call mailCheck using Employee reference--");
      e.mailCheck();
   }
}

Quando você compila a classe acima, obtém o seguinte erro -

Employee.java:46: Employee is abstract; cannot be instantiated
      Employee e = new Employee("George W.", "Houston, TX", 43);
                   ^
1 error

Herdando a classe abstrata

Podemos herdar as propriedades da classe Employee assim como a classe concreta da seguinte maneira -

Exemplo

/* File name : Salary.java */
public class Salary extends Employee {
   private double salary;   // Annual salary
   
   public Salary(String name, String address, int number, double salary) {
      super(name, address, number);
      setSalary(salary);
   }
   
   public void mailCheck() {
      System.out.println("Within mailCheck of Salary class ");
      System.out.println("Mailing check to " + getName() + " with salary " + salary);
   }
 
   public double getSalary() {
      return salary;
   }
   
   public void setSalary(double newSalary) {
      if(newSalary >= 0.0) {
         salary = newSalary;
      }
   }
   
   public double computePay() {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
}

Aqui, você não pode instanciar a classe Employee, mas pode instanciar a classe Salary e, usando essa instância, pode acessar todos os três campos e sete métodos da classe Employee, conforme mostrado abaixo.

/* File name : AbstractDemo.java */
public class AbstractDemo {

   public static void main(String [] args) {
      Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
      Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00);
      System.out.println("Call mailCheck using Salary reference --");
      s.mailCheck();
      System.out.println("\n Call mailCheck using Employee reference--");
      e.mailCheck();
   }
}

Isso produz o seguinte resultado -

Resultado

Constructing an Employee
Constructing an Employee
Call mailCheck using Salary reference --
Within mailCheck of Salary class 
Mailing check to Mohd Mohtashim with salary 3600.0

 Call mailCheck using Employee reference--
Within mailCheck of Salary class 
Mailing check to John Adams with salary 2400.0

Métodos Abstratos

Se você deseja que uma classe contenha um método específico, mas deseja que a implementação real desse método seja determinada por classes filhas, você pode declarar o método na classe pai como um abstrato.

  • abstract palavra-chave é usada para declarar o método como abstrato.

  • Você tem que colocar o abstract palavra-chave antes do nome do método na declaração do método.

  • Um método abstrato contém uma assinatura de método, mas nenhum corpo de método.

  • Em vez de chaves, um método abstrato terá dois pontos semoi (;) no final.

A seguir está um exemplo do método abstrato.

Exemplo

public abstract class Employee {
   private String name;
   private String address;
   private int number;
   
   public abstract double computePay();
   // Remainder of class definition
}

Declarar um método como abstrato tem duas consequências -

  • A classe que o contém deve ser declarada como abstrata.

  • Qualquer classe que herde a classe atual deve substituir o método abstrato ou declarar-se como abstrata.

Note- Eventualmente, uma classe descendente tem que implementar o método abstrato; caso contrário, você teria uma hierarquia de classes abstratas que não podem ser instanciadas.

Suponha que a classe Salary herde a classe Employee, então ela deve implementar o computePay() método como mostrado abaixo -

/* File name : Salary.java */
public class Salary extends Employee {
   private double salary;   // Annual salary
  
   public double computePay() {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
   // Remainder of class definition
}