Java - Astrazione

Come da dizionario, abstractionè la qualità di trattare le idee piuttosto che gli eventi. Ad esempio, se si considera il caso della posta elettronica, dettagli complessi come ciò che accade non appena si invia un'e-mail, il protocollo utilizzato dal proprio server di posta elettronica vengono nascosti all'utente. Pertanto, per inviare un'e-mail è sufficiente digitare il contenuto, menzionare l'indirizzo del destinatario e fare clic su invia.

Allo stesso modo nella programmazione orientata agli oggetti, l'astrazione è un processo di nascondere i dettagli di implementazione all'utente, solo la funzionalità verrà fornita all'utente. In altre parole, l'utente avrà le informazioni su cosa fa l'oggetto invece di come lo fa.

In Java, l'astrazione si ottiene utilizzando classi e interfacce astratte.

Classe astratta

Una classe che contiene il file abstract la parola chiave nella sua dichiarazione è nota come classe astratta.

  • Le classi astratte possono o non possono contenere metodi astratti , cioè metodi senza corpo (public void get ();)

  • Ma, se una classe ha almeno un metodo astratto, la classe must essere dichiarato astratto.

  • Se una classe viene dichiarata astratta, non può essere istanziata.

  • Per usare una classe astratta, devi ereditarla da un'altra classe, fornire implementazioni ai metodi astratti in essa contenuti.

  • Se erediti una classe astratta, devi fornire implementazioni a tutti i metodi astratti in essa contenuti.

Esempio

Questa sezione fornisce un esempio della classe astratta. Per creare una classe astratta, usa semplicemente il fileabstract parola chiave prima della parola chiave della classe, nella dichiarazione della 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;
   }
}

Puoi osservare che, ad eccezione dei metodi astratti, la classe Employee è la stessa della normale classe in Java. La classe ora è astratta, ma ha ancora tre campi, sette metodi e un costruttore.

Ora puoi provare a creare un'istanza della classe Employee nel modo seguente:

/* 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 compili la classe sopra, ti dà il seguente errore:

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

Ereditare la classe astratta

Possiamo ereditare le proprietà della classe Employee proprio come la classe concreta nel modo seguente:

Esempio

/* 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;
   }
}

Qui, non è possibile creare un'istanza della classe Employee, ma è possibile creare un'istanza della classe Salary e utilizzando questa istanza è possibile accedere a tutti i tre campi e sette metodi della classe Employee come mostrato di seguito.

/* 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();
   }
}

Questo produce il seguente risultato:

Produzione

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

Metodi astratti

Se si desidera che una classe contenga un particolare metodo ma si desidera che l'effettiva implementazione di quel metodo sia determinata dalle classi figlie, è possibile dichiarare il metodo nella classe genitore come astratto.

  • abstract viene utilizzata per dichiarare il metodo come astratto.

  • Devi posizionare il file abstract parola chiave prima del nome del metodo nella dichiarazione del metodo.

  • Un metodo astratto contiene una firma del metodo, ma nessun corpo del metodo.

  • Invece delle parentesi graffe, un metodo astratto avrà un punto e virgola (;) alla fine.

Di seguito è riportato un esempio del metodo astratto.

Esempio

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

Dichiarare un metodo come astratto ha due conseguenze:

  • La classe che lo contiene deve essere dichiarata astratta.

  • Qualsiasi classe che eredita la classe corrente deve sovrascrivere il metodo astratto o dichiararsi astratta.

Note- Alla fine, una classe discendente deve implementare il metodo astratto; altrimenti, avresti una gerarchia di classi astratte che non possono essere istanziate.

Supponiamo che la classe Salary erediti la classe Employee, quindi dovrebbe implementare l'estensione computePay() metodo come mostrato di seguito -

/* 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
}