Java >> Tutoriel Java >  >> Java

Encapsulation en Java

L'encapsulation est l'un des quatre piliers du concept OOP. L'héritage, le polymorphisme et l'abstraction sont les trois autres.

En Java, l'encapsulation combine les données (variables) et le code qui agit sur les données (méthodes) en une seule unité. L'encapsulation signifie que les variables d'une classe sont cachées aux autres classes et ne sont accessibles que par les méthodes de sa classe actuelle. Par conséquent, il est également connu sous le nom de dissimulation de données.

L'objectif de l'encapsulation est de garder les détails d'implémentation cachés aux utilisateurs. Les autres membres de la même classe ne peuvent accéder qu'à un membre de données privé. Aucune classe extérieure n'a accès aux données privées membres (variable) d'une classe.

Cependant, supposons que nous créons des méthodes getter et setter publiques pour mettre à jour (par exemple, void setEmployee(int ID)) et lire (par exemple, int getEmployee()) les champs de données privés. Dans ce cas, la classe extérieure peut utiliser ces méthodes publiques pour accéder à ces champs de données privés. Les champs privés et leur implémentation sont cachés aux classes extérieures puisque les méthodes publiques ne peuvent accéder qu'aux données.

Encapsulation en Java

Pour implémenter l'encapsulation en Java,

  • Déclarer les variables d'une classe comme privées.
  • Pour modifier et inspecter les valeurs des variables, fournissez des méthodes setter et getter publiques.

Ensuite, nous examinerons la syntaxe que vous utilisez lors de l'implémentation de l'encapsulation en Java. La syntaxe est la suivante :

<Access_Modifier> class <Class_Name> {

 private <Data_Members>;

 private <Data_Methods>;

}

Explorons l'exemple de programme ci-dessous pour mieux comprendre le processus d'encapsulation.

Exemple :le code suivant illustre comment implémenter l'encapsulation en Java.

/* File name : CodeEncapsulation.java */

public class CodeEncapsulation {

   private String name;
   private String idNum;
   private int age;

   public int getAge() {
      return age;
   }

   public String getName() {
      return name;
   }

   public String getIdNum() {
      return idNum;
   }

   public void setAge( int newAge) {
      age = newAge;
   }

   public void setName(String newName) {
      name = newName;
   }

   public void setIdNum( String newId) {
      idNum = newId;
   }
}

Les méthodes publiques setXXX() et getXXX() permettent d'accéder aux variables d'instance de la classe CodeEncapsulation. Ces méthodes sont communément appelées getters et setters. Par conséquent, toute classe qui a besoin d'accéder aux variables doit utiliser ces getters et setters. Les variables de la classe CodeEncapsulation sont accessibles avec le programme suivant :

/* Filename : RunCodeEncapsulation.java */
public class RunCodeEncapsulation {

   public static void main(String args[]) {
      CodeEncapsulation encapVar = new CodeEncapsulation();
      encapVar.setName("Green");
      encapVar.setAge(53);
      encapVar.setIdNum("TY905");

      System.out.print("Name : " + encapVar.getName() + " Age : " + encapVar.getAge());
   }
}

Méthodes de Getter et Setter

Acquéreur

Une méthode getter est une méthode qui vous permet d'accéder et de récupérer une instance d'une variable privée.

Passeur

La méthode setter est capable de mettre à jour ou de définir une instance de variable privée.

package Codeunderscored;

public class CodeEmployee {

private String c_name;

public String getCodeName() {

return c_name;

}

public void setCodeName(String c_name){  

this.c_name=c_name ;

}

}

package Codeunderscored;

public class CodeTestGettersSetters {

public static void main(String[] args) {

CodeEmployee empOne = new CodeEmployee();

empOne.setCodeName("Green");

System.out.println(empOne.getCodeName());

}

}

//Output: Green

Avantages de l'encapsulation

  • Vous pouvez rendre une classe en lecture seule ou en écriture seule en ne donnant qu'une méthode setter ou getter.
  • En d'autres termes, les méthodes getter et setter sont facultatives.
  • Les IDE les plus courants offrent la possibilité de générer des getters et des setters. Créer une classe fermée en Java est donc simple et rapide. Par extension, cela facilite l'ensemble du processus d'écriture de programmes.
  • L'encapsulation dans Java vous permet de réutiliser votre code.
  • L'encapsulation vous permet d'apporter rapidement des modifications au code existant.
  • Cela vous donne un contrôle total sur vos données. Vous pouvez écrire la logique à l'intérieur de la méthode setter si vous souhaitez uniquement définir la valeur de id sur une valeur supérieure à 100. Vous pouvez implémenter une logique dans les méthodes setter pour empêcher le stockage d'entiers négatifs.
  • Une classe peut avoir un contrôle total sur le contenu de ses champs.
  • Parce que les autres classes ne pourront pas accéder aux données via les membres de données privées, c'est un moyen de masquer les données en Java. Il est simple de tester la classe ci-jointe. Par conséquent, il est plus adapté aux tests unitaires.
  • Le code de test unitaire écrit avec encapsulation est simple.

Encapsulation en Java :un exemple simple

Regardons un exemple d'encapsulation simple avec un seul champ et des méthodes setter et getter.

// A Java class that is completely enclosed. It has a getter and setter method and a private data member.

package com.codeunderscored;  

public class CodeStudent{  

  //the data member  is  private
  private String name;  

  // name's getter method
  public String getName(){  
    return name;  
  }  
  //names' setter method
  public void setName(String name){  
    this.name=name  
    }  
}  


//The Java class here tests the encapsulated class above
package com.codeunderscored;  

class CodeTest{  

  public static void main(String[] args){  

    //first, create an instance of the encapsulated class  

    CodeStudent codeStudent = new CodeStudent();  

    // using the setter method to assign value to the name member  
    codeStudent.setName("Green");  

    // Using the name's get method to fetch the value of the name member  
    System.out.println(codeStudent.getName());  
  }  
}  

Ce qui suit est une classe en lecture seule.

//Only getter methods are available in this Java class.

public class CodeStudent{  

  //The data member is  private
  private String code_school="Code Underscored";  

  // code_school's getter method
  public String getCodeSchool(){  
    return code_school;  
  }  
}

Vous ne pouvez plus modifier la valeur du membre de données code_school "Code Underscored".

codeStudent.setCodeSchool("w3schools");// the code renders a compile time error

Ce qui suit est une classe en écriture seule :

//Only setter methods are available in this Java class.
public class CodeStudent{  

  //data member  is private
  private String code_school;  

  //code_school's setter method
  public void setCodeSchool(String code_school){  
    this.code_school=code_school;  
  }  
}  

Vous ne pouvez plus accéder à la valeur de code_school ; à la place, vous ne pouvez mettre à jour que la valeur du composant de données code_school.

System.out.println(codeStudent.getCodeSchool());//There is no such procedure, resulting in a Compile Time Error.
System.out.println(codeStudent.code_school);//Because the college data member is private, there is a Compile Time Error.
//As a result, it is not accessible from outside the class.

Un autre exemple Java d'encapsulation

Regardons un autre exemple d'encapsulation avec seulement quatre champs et des fonctions setter et getter.

//   An Account class that is completely contained.
// It has a getter and setter method and a private data member.

class CodeAccount {  

  //The data members are private

  private long code_acc_no;  
  private String code_name,code_email;  
  private float code_amount;  

  //These getter and setter methods  are all public
  public long getCodeAccNo() {  
    return code_acc_no;  
  }  
  public void setCodeAccNo(long code_acc_no) {  
    this.code_acc_no = code_acc_no;  
  }  
  public String getCodeName() {  
    return code_name;  
  }  
  public void setCodeName(String code_name) {  
    this.code_name = code_name;  
  }  
  public String getCodeEmail() {  
    return code_email;  
  }  
  public void setCodeEmail(String code_email) {  
    this.code_email = code_email;  
  }  
  public float getCodeAmount() {  
    return code_amount;  
  }  
  public void setCodeAmount(float code_amount) {  
    this.code_amount = code_amount;  
  }  

}  




//A Java class for testing the encapsulated Account class.

public class CodeTestEncapsulation {  

  public static void main(String[] args) {  

    //creation of CodeAccount class instance
    CodeAccount codeAccount=new CodeAccount();  

    //Using the setter methods to set values
    codeAccount.setCodeAccNo(111THY78645);  
    codeAccount.setCodeName("Code Underscored");  
    codeAccount.setCodeEmail("[email protected]");  
    codeAccount.setCodeAmount(250f);  

    // using the getter methods to fetch respective  values
    System.out.println(codeAccount.getCodeAccNo()+" "+codeAccount.getCodeName()+" "+codeAccount.getCodeEmail()+" "+codeAccount.getCodeAmount());  
  }  
}  

Exemple :Encapsulation en Java

class CodeArea {

  // fields for calculating the area
  int c_length;
  int c_breadth;

  // constructor for values initialization

  CodeArea(int c_length, int c_breadth) {
    this.c_length = c_length;
    this.c_breadth = c_breadth;
  }

  // method responsible for area calculate
  public void getCodeArea() {
    int resultantArea = c_length * c_breadth;
    System.out.println("Resultant Area is: " + resultantArea);
  }
}

class Main {
  public static void main(String[] args) {

    // create object of Area
    // pass value of length and breadth
    resultantArea rec = new resultantArea(12, 16);
    rec.getCodeArea();
  }
}

Nous avons établi une classe appelée CodeArea dans l'exemple précédent. L'objectif principal de la classe est de calculer l'aire. Deux variables, c_length et c_breadth, plus une méthode, getCodeArea, sont nécessaires pour déterminer la zone. En conséquence, nous avons combiné ces attributs et méthodes en une seule classe.

Les propriétés et les méthodes de cette classe peuvent également être accessibles depuis d'autres classes. Par conséquent, il ne s'agit pas de dissimulation de données. Ce n'est qu'un résumé. Nous regroupons simplement des codes comparables. Alors que beaucoup de gens pensent que l'encapsulation est une dissimulation de données, ce n'est pas tout à fait exact. L'encapsulation est le regroupement de domaines et de procédures similaires. Vous pouvez l'utiliser pour dissimuler des informations. Le masquage des données n'est donc pas la même chose que l'encapsulation.

Quel est le but de l'encapsulation ?

L'encapsulation en Java nous permet de regrouper les champs et méthodes pertinents, ce qui rend notre code plus clair et plus facile à lire.

Il facilite la gestion des valeurs de nos champs de données. Par exemple,

class CodeEmployee {
  private int age;

  public void setCodeAge(int c_age) {
    if (age >= 0) {
      this.c_age = c_age;
    }
  }
}

La variable c_age est maintenant privée et la logique est appliquée à l'intérieur de la méthode setCodeAge(). c_age n'est plus un facteur négatif. Nos champs de classe peuvent exister en lecture seule ou en écriture seule. Ce dernier dépend de l'utilisation des méthodes getter et setter. Par exemple,

getCodeName()  // provides access for read-only
setCodeName() // provides access for write-only

Il aide au découplage des composants du système. Nous pouvons, par exemple, diviser le code en plusieurs bundles. Ces composants détachés (bundle) peuvent être construits, testés et débogués à leur propre rythme. De plus, toute modification apportée à un composant n'a aucun impact sur les autres. L'encapsulation peut également être utilisée pour dissimuler des données. Si nous définissons les variables de longueur et de largeur sur private dans l'exemple précédent, l'accès à ces champs est restreint. Ils sont également tenus secrets des classes supérieures. C'est ce qu'on appelle la dissimulation des données.

Masquer des données

La dissimulation des données est une méthode permettant de limiter l'accès des membres des données à nos données en masquant les détails de mise en œuvre. L'encapsulation permet également de masquer les données. Vous pouvez masquer des données en utilisant des modificateurs d'accès.

Voici les quatre spécificateurs d'accès :

Par défaut

La première ligne de masquage des données est la valeur par défaut. Dans le cas où aucun spécificateur d'accès n'est explicitement spécifié pour une classe Java donnée, le compilateur utilisera "default" comme spécificateur d'accès. Le spécificateur d'accès par défaut est très similaire au spécificateur d'accès public en termes de fonctionnalité.

Public

Le modificateur d'accès le moins restrictif est celui-ci. Les méthodes et les propriétés avec le modificateur public peuvent être accessibles à la fois à l'intérieur et à l'extérieur de votre classe actuelle.

L'API publique de votre classe et tout composant que vous incluez incluent des méthodes et des attributs publics. Ce n'est généralement jamais une bonne idée pour un attribut. Soyez donc prudent lorsque vous appliquez cette modification à une méthode. Lorsqu'une méthode est rendue publique, elle doit être correctement décrite et capable de gérer les valeurs d'entrée. N'oubliez pas que cette technique sera utilisée par une partie de votre programme, ce qui la rendra difficile à mettre à jour ou à éliminer.

Votre API publique doit, en général, être aussi légère que possible. Seules les méthodes utilisées par d'autres parties du programme ou des clients externes sont incluses dans les API publiques. Le spécificateur d'accès public donne à la classe un accès à ses spécifications d'accès pour un accès depuis n'importe où dans le programme.

Exemple :

package Codeunderscored;

class CodeVehicle {

public int c_tires;

public void CodeDisplay() {

System.out.println("Codeunderscored owns a vehicle.");

System.out.println("The vehicle has " + c_tires + " number of wheels.");

}

}

public class CodeTestVehicle {

public static void main(String[] args) {

CodeVehicle codeVehicle = new CodeVehicle();

codeVehicle.tires = 8;

codeVehicle.display();

}

}

//Output: Codeunderscored owns a vehicle.
// It has 8 number of wheels.

Privé

Le modificateur privé, le modificateur d'accès le plus restrictif et le plus largement utilisé, limite l'accès à un attribut ou à une méthode aux autres membres de la même classe. Cet attribut ou cette méthode n'est pas accessible aux sous-classes ou aux autres classes du même package ou d'un package différent.

Par défaut, choisissez le modificateur privé pour tous les attributs et méthodes internes que vous ne devez pas appeler depuis des classes extérieures. Vous devrez peut-être faire une exception à cette règle lors de l'utilisation de l'héritage. De plus, certaines sous-classes qui nécessitent un accès direct à une propriété ou à une méthode interne devraient être exemptées. Au lieu d'utiliser le modificateur private, vous devez utiliser le modificateur protected. Les membres de données utilisent le spécificateur d'accès privé pour l'accessibilité. D'autre part, les méthodes de données sont limitées à la classe elle-même.

Exemple :

package Codeunderscored;

class CodeEmployee {

private int code_rank;

public int getCodeRank() {

return code_rank;

}

public void setCodeRank(int code_rank) {

this.code_rank = code_rank;

}

}

public class CodeTestEmployee {

public static void main(String[] args) {

CodeEmployee codeEmployee = new CodeEmployee();

codeEmployee.setCodeRank(1);

System.out.println("The Code Employee's rank is " + codeEmployee.getCodeRank());

}

}

// Output:
// The Code Employee's rank is 1

Protégé

Comme le spécificateur d'accès privé, le spécificateur d'accès protégé protège les méthodes de classe et les membres. La principale distinction est qu'au lieu de restreindre l'accès à une seule classe, le package dans son ensemble est restreint. Les méthodes internes qui doivent être appelées ou remplacées par des sous-classes reçoivent généralement le modificateur protected. Vous pouvez également utiliser le modificateur protected pour donner aux sous-classes un accès direct aux attributs internes d'une super-classe.

package Codeunderscored;

class Computer {

protected String code_stream;

protected void CodeDisplay() {

System.out.println("Hello, people refer to me as the " + code_stream + " Technology");

}

}

public class SuperComputer extends Computer {

public static void main(String[] args) {

SuperComputer superComputer = new SuperComputer();

superComputer.stream = " super computer  because of my ";

SuperComputer.CodeDisplay();

}

}

//Output:
// Hello, people refer to me as the  super computer  because of my Technology

Exemple :Masquage de données

class CodeEmployee {

  // private field
  private int c_age;

  // getter method
  public int getCodeAge() {
    return c_age;
  }

  // setter method
  public void setCodeAge(int c_age) {
    this.c_age = c_age;
  }
}

class Main {
  public static void main(String[] args) {

    // creating a Person's Object
    CodeEmployee empOne = new CodeEmployee();

    // using the setter method to change the  c_age
    empOne.setCodeAge(32);

    // using the getter method to access c_age
    System.out.println("My Current age is :" + empOne.getCodeAge());
  }
}

Nous avons un champ privé c_age dans l'exemple ci-dessus. Vous ne pouvez pas y accéder depuis l'extérieur de la classe car il est privé. Dans cet exemple, nous avons utilisé les méthodes publiques getCodeAge() et setCodeAge() pour récupérer c_age. Celles-ci sont connues sous le nom de méthodes getter et setter. Nous avons pu interdire l'accès illégal de l'extérieur de la classe en rendant l'âge secret. C'est la dissimulation des données. Les tentatives d'accès au champ c_age à partir de la classe Main obtiendront une erreur.

// error: c_age has private access in CodeEmployee
empOne.c_age = 36;

Encapsulation contre abstraction

L'abstraction et l'encapsulation sont fréquemment confondues. Laissez-nous enquêter-

  • L'encapsulation concerne principalement le "comment" pour obtenir des fonctionnalités.
  •  
  • L'abstraction concerne principalement "ce" qu'une classe peut accomplir.

Un téléphone mobile est un moyen facile de comprendre la différence où les circuits sophistiqués de la carte de circuit imprimé sont encapsulés dans un écran tactile, avec une interface pour l'abstraire.

Exemple :programme de démonstration de l'accès aux variables à l'aide de l'encapsulation en Java

class CodeEncapsulate {

	// The following private variables declared below can only be accessed by the class's public methods

	private String codeName;
	private int codeRoll;
	private int codeAge;

	// getting the method for age to access
	// private variable codeAge
	public int getCodeAge() { return codeAge; }

	// getting the method for name to access
	// private variable codeName
	public String getName() { return codeName; }

	// getting the method for roll to access
	// private variable codeRoll
	public int getCodeRoll() { return codeRoll; }

	// setting the method for age to access
	// private variable codeAge
	public void setCodeAge(int codeAge) { codeAge = codeAge; }

	// setting the method for codeName to access
	// private variable codeName
	public void setCodeName(String codeName)
	{
		codeName = codeName;
	}

	// set method for roll to access
	// private variable geekRoll
	public void setRoll(int newRoll) { geekRoll = newRoll; }
}

public class TestCodeEncapsulation {
	public static void main(String[] args)
	{
		CodeEncapsulate codeEncapsulate = new CodeEncapsulate();

		// setting values of the variables
		codeEncapsulate.setCodeName("Green");
		codeEncapsulate.setCodeAge(34);
		codeEncapsulate.setCodeRoll(198);

		// Displaying the variable values
		System.out.println("Code's name: " + codeEncapsulate.getCodeName());
		System.out.println("Code's age: " + codeEncapsulate.getAge());
		System.out.println("Code's roll: " + codeEncapsulate.getRoll());

		// Direct access of CodeRoll is not possible because of encapsulation
		// System.out.println("Code's roll: " +// codeEncapsulate.CodeName);
	}
}

Conclusion

En Java, l'encapsulation combine le code et les données en une seule unité, telle qu'une capsule contenant plusieurs médicaments. De plus, en Java, nous pouvons créer une classe entièrement fermée en gardant tous les membres de données de la classe privés. Nous pouvons maintenant définir et obtenir des données à l'aide des méthodes setter et getter. La classe Java Bean représente une classe entièrement contenue. Il est fréquemment utilisé pour implémenter une méthode de masquage de données. Cette stratégie minimise l'accessibilité des propriétés à la classe actuelle et contrôle et restreint l'accès externe à ces attributs à l'aide de méthodes getter et setter publiques. Ces méthodes permettent de spécifier quelles caractéristiques peuvent être lues ou mises à jour et de valider la nouvelle valeur avant d'apporter une modification.

L'encapsulation a la propriété fondamentale de masquer les données et d'assurer la sécurité des données des utilisateurs. L'encapsulation est une bonne pratique POO. Cependant, il fonctionne mieux lorsqu'il est associé à une solution APM fiable telle que Retrace pour la surveillance des erreurs.


Balise Java