<!--
Live coding
Idea diagramme
Correction TP2 exo 1 comparable compareto
Correction TP2 exo 2 statistiques
En live coding tous ensemble
Encapsulation
variable
méthode
classe
package
module
bibliothèque

-->
[[Glossaire#Encapsuler (programmation)|L'encapsulation]] consiste à présenter **une [[Glossaire#Interface (programmation)|interface]] publique** cohérente **indépendante de ses détails d'[[Glossaire#Implémentation|implémentation]]** internes (privés).
### Motivations
- Modifier les structures de données internes (détails d'implémentation) sans modifier l’**interface publique** ni le comportement d'une abstraction
- Masquage des données : maintenir les détails internes d'un objet cachés du monde extérieur
- Ajouter aisément des règles de validation et de cohérence des **invariants**
- Voir aussi : [[Parse don’t validate]]
- Éviter l’[[Glossaire#Antipattern|antipattern]] du [plat de spaghetti](https://fr.wikipedia.org/wiki/Programmation_spaghetti "Programmation spaghetti") qui ne permet pas de déterminer le qui, le quoi et le comment d’une modification de données[^2]
- Augmenter [[Glossaire#Cohésion|la cohésion]] en groupant les données et les traitement poches les uns des autres
- Réduire [[Glossaire#Couplage|le couplage]] pour s'assurer que les seulement certaines parties des données sont utilisés par des traitements associés
- Offrir une [[Glossaire#Interface (programmation)|interface]] orientée **services** et **responsabilités** et la considérer comme une **"boîte noire"**
---
### Encapsulation en Java
En java, on considère que l'encapsulation concerne plus spécfiquement :
- des [[3.3 - Encapsulation en Java#Mécanismes de groupement d’informations en Java|mécanismes de groupement d'informations]] et de comportements: module, package, classe, objet, record, enum, méthodes ...
- des [[3.3 - Encapsulation en Java#Modificateurs de visibilité|modificateurs de visibilité]] : public, private, protected, visibilité package
## Portée lexicale (blocs)
Un **bloc** définit la **[portée lexicale](https://fr.wikipedia.org/wiki/Port%C3%A9e_(informatique)#Port%C3%A9e_lexicale)** (lexical scope) des entités qu'il contient.
Un bloc est déclaré à l'aide d'accolades `{` `}`.
Une entité déclarée dans un bloc n'est accessible qu'à l'intérieur de celui-ci à moins d'être retournée ou publiée.
> [!example] Exemple 1
> ```text
> A
> {
> B
> }
> ```
Dans l'exemple simplifié ci-dessus, une entité `A` est déclarée.
Un bloc est créé dans lequel une entité `B` est déclarée.
L'entité `B` n'est accessible que depuis l'intérieur du bloc.
On verra en pratique que selon le type de bloc c'est un peu différent.
Quelques types de blocs qu'on peut trouver une séquence d'instructions
- bloc anonyme
- if / else / else if
- for / while / do while
- switch / case
- try / catch
> [!example]- Exemples de blocs en Java
> ```java
> void main(String[] args) { // Déclaration d'un bloc de méthode
>
> int a = 1;
>
> // bloc local
> {
> // a du bloc parent est accessible
> int b = 2 + a;
> IO.println(b);
> }
> // TODO: décommenter pour voir ce qu'il se passe
> // b = 0;
>
> if (a == 1) { // bloc quand la condition est vraie
> int c = 1;
> } else { // bloc quand la condition est fausse
> int c = 2;
> }
>
> // Bloc de déclaration des valeurs contenues dans un tableau
> double[] temperatures = {
> 0.0,
> 1.5,
> 27.5,
> 37.5,
> 12.7,
> };
>
> for (double temperature : temperatures) {
> // Dans une boucle foreach, la valeur temperature
> // a sa portée uniquement à l'intérieur de la boucle IO.println("Température : " + temperature);
> }
> // La variable temperature n'est pas la même que dans la boucle for
> double temperature = 34.7;
>
> String someString = "A";
> switch (someString) {
> case "A": {
> }
> case "B": {
> }
> default: {
> }
> }
>
> try {
> // Some risky computation
> } catch (Exception e) {
> // When it fails
> } finally {
> // Regardless is succeeds or fails
> }
>
> }
> ```
> [!note]- Bloc anonyme local
> Il est possible de déclarer **un bloc de code anonyme** en Java pour restreindre la portée des variable déclarée (même si c'est rarement utilisé et peu [[Idiomatique]]).
> [!note]- Exemple dans Jshell
> ```text
>int a = 1;
>a ==> 1
>
> {
> int b = 2 + a;
> }
>
> a
> a ==> 1
>
> b
> ```
>
> > [!success]- Quelle est la valeur de b ?
> > ```text
> > | Error:
> > | cannot find symbol
> > | symbol: variable b
> > | b
> > | ^
> >```
> >
## Mécanismes de groupement d’informations en Java
Les mécanismes de groupement d'informations participent à [[Glossaire#Encapsulation (en java)|l'encapsulation]].
### Variables
Les variables encapsulent le résultat d'expressions ou de valeurs en leur donnant un nom.
> [!note] Conventions pour les variables
> - doit être déclaré dans un bloc
> - nom en `camelCase`
> - ne commence par par un nombre
Pratiques recommandées
- nom de variable lisible et compréhensible par un humain
```java
// Pas bien
String xtn = "Foo";
// Mieux
String extension = "Foo"
```
### Routines (méthodes/fonctions)
Une [[Glossaire#Méthode|méthode]] une séquence d'instructions et peut ainsi encapsuler **des données** et **du comportement réutilisable**.
La [[Glossaire#Signature de méthode|signature d'une méthode]] définit son **[[Glossaire#API|contrat d'interface]]** (API) vis à vis de ses **appelants** éventuels.
> [!note] Conventions pour les méthodes
> - doit être déclaré dans une classe
> - nom en `camelCase`
> - nom ne commence par par un nombre
> - nom en ascii (même si l'unicode est supporté) : lettres non accentuées et chiffres
```java
class Chasseur {
private int nombreDeBalles=2;
// Méthode d'instance qui opère sur l'état interne de l'objet
// En évitant ce dernier d'être accessible depuis l'extérieur
public void tire(){
this.nombreDeBalles--;
// boit une bière
}
public void recharge(int balles){
this.nombreDeBalles+=2;
}
// Méthode statique et publique (donc globale)
// Car tous les chasseurs connaissent la chanson qui est toujours la même
public static String chanter(){
return "...";
}
}
```
### Objets et leurs modèles de définition (classes ...)
En Java, les objets peuvent sont définis syntaxiquement à l'aide de modèles de définition d'objets.
- classe : `class`
- enregistrement immuable: `record`
- classe abstraite : `abstract class`
- interface : `interface`
- enumération : `enum`
> [!note] Conventions pour les classes et assimilés
> - extension du fichier `.java`
> - le nom de la classe est identique au nom de fichier
> - le nom de la classe est en `PascalCase`
```java
// Fichier SomeClass.java
class SomeClass {
// bloc délimitant la portée à l'intérieur d'une classe
class InnerClass {
// bloc délimitant la portée d'une classe interne
}
}
record SomeRecord(int number) {
// bloc délimitant la portée d'un record
}
enum SomeEnum {
// bloc délimitant la portée d'un record
}
```
### Packages
Les packages sont **des espaces de nommage** qui permettent de regrouper des fichiers qui ont une proximité
> [!note] Conventions pour les packages
> - nom de package de base est l'URL de l'organisation à l'envers.
> - le nom de package correspond à la hiérarchie de dossier où se trouve le fichier
Ex. pour le domaine `coda.school`, les noms de package commenceront par `school.coda` et seront suivis de leur spécificité.
```java
// Fichier dans src/main/java/school/coda/tictactoe
package school.coda.tictactoe;
public class TicTacToe {
static void main() {
//
}
}
```
### Modules
Les modules permettent de grouper et de déterminer les règles d'accès à des packages dans un projet java.
Hors périmètre de ce cours.
Pour aller plus loin : https://www.jmdoudoux.fr/java/dej/chap-modules.htm
## Jar
Unité de déploiement (bibliothèque) pouvant être intégrée dans un autre programme Java ou servant de point d'entrée à la commande `java`.
Le sujet des [[Glossaire#Jar|jars]] sera approfondi dans [[4.2 - Maven|le module consacré à la gestion des dépendances]].
## Modificateurs de visibilité
Les [[Glossaire#Modificateur de visibilité|modificateurs de visibilité]] permettent de déterminer si une donnée ou un comportement peut être accédée par une autre partie d'un programme.
Pour approfondir : https://dev.java/learn/classes-objects/more-on-classes/#controlling-access
### Visibilité d'attribut
Modificateurs de visibilité d'attribut:
Par niveau de visibilité décroissant
- `private` : n'est accessible que dans l'instance de la classe
- `protected` : est accessible dans l'instance de la classe et ses descendands
- ` ` : (par défaut : visibilité package) : est accessible aux entités situées dans le même [[Glossaire#Package (Java)|package]]
- `public` : est accessible aux entités qui peuvent accéder à la classe
> [!tip] les constantes déclarées dans des `interface` sont toujours `public`
### Visibilité de méthode
Modificateurs de visibilité de méthode :
Par niveau de visibilité décroissant
- `private` : n'est accessible que dans l'instance de la classe
- `protected` : n'est accessible que dans l'instance de la classe et ses descendants
- ` ` : (par défaut : visibilité package) : n'est accessible qu'aux entités situées dans le même [[Glossaire#Package (Java)|package]]
- `public` : est accessible aux entités qui peuvent accéder à la classe
> [!tip] les méthodes déclarées dans des `interface` sont toujours `public`
### Visibilité de classe
Modificateurs de visibilité de classe :
#### Classes externes
Pour les classes externes (associées à un fichier)
Pas niveau de visibilité décroissant
- ` ` : (par défaut : visibilité package) : n'est accessible qu'aux entités situées dans le même [[Glossaire#Package (Java)|package]]
- `public` : est accessible aux entités qui peuvent accéder au package / module
#### Classes internes non statiques
> [!important] Dans les classes internes non statiques, les variables d'instance (non `static`) de la classe qui a déclaré la classe interne sont accessibles.
Par niveau de visibilité décroissant
- `private` : n'est accessible que dans l'instance dans laquelle la classe interne statique est déclarée
- `protected` : n'est accessible que dans l'instance de la classe où la classe statique est déclarée ainsi que et ses descendants
- ` ` : (par défaut : visibilité package) : n'est accessible qu'aux entités situées dans le même [[Glossaire#Package (Java)|package]] à condition que la classe où elle a été déclarée est également accessible
- `public` : est accessible aux entités qui peuvent accéder à la classe dans laquelle elle a été déclarée
```java
package cours.intro;
public class Outer {
private int nombre;
public Outer(int nombre) {
this.nombre = nombre;
}
public Outer() {
this.nombre = 1;
}
public String callInnerNonStatic() {
return new InnerNonStatic().shout();
}
class InnerNonStatic {
String shout() {
return ("" + nombre).toUpperCase();
}
}
}
```
Usage
```java
// Ne compile pas
new Outer.InnerNonStatic().shout();
// On doit passer par l'instance où elle est déclarée
new Outer(2).callInnerNonStatic();
// 2
```
#### Classes internes statiques
> [!important] Les variables d'instance (non `static`) de la classe déclarant une classe interne statique ne sont pas accessibles depuis cette classe.
- `private` : n'est accessible que dans l'instance dans laquelle la classe interne statique est déclarée
- `protected` : n'est accessible que dans l'instance de la classe où la classe statique est déclarée ainsi que et ses descendants
- ` ` : (par défaut : visibilité package) : n'est accessible qu'aux entités situées dans le même [[Glossaire#Package (Java)|package]] à condition que la classe où elle a été déclarée est également accessible
- `public` : est accessible aux entités qui peuvent accéder à la classe dans laquelle elle a été déclarée
```java
package cours.intro;
public class Outer {
private int nombre;
public Outer(int nombre) {
this.nombre = nombre;
}
static class InnerStatic {
String greet() {
// Ne compile pas
// La classe interne statique n'a pas accès
// aux variables d'instance de la classe Outer
// 👇
String numeroCrie = ("" + nombre).toUpperCase():
return "Hello !";
}
}
}
```
Usage
```java
var greetings = new Outer.InnerStatic().greet();
// Hello !
```
> [!tip] les classes internes sont parfois utiles pour rapprocher des classes utilitaires vers là où elles sont utilisées
> ```java
> public interface Map {
> interface Entry {
>
> }
> }
> ```
> [!tip] Les types imbriqués dans des `interface` sont automatiquement `public` et `static`
### Visibilité au sein d’un module
Hors périmètre de ce cours.
Pour aller plus loin : https://www.jmdoudoux.fr/java/dej/chap-modules.htm
## À suivre
[[3.4 - Héritages en Java]]