<!--
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 général#Encapsuler (programmation)|L'encapsulation]] consiste à présenter **une [[Glossaire général#Interface (programmation)|interface]] publique** cohérente **indépendante de ses détails d'[[Glossaire général#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 général#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 général#Cohésion|la cohésion]] en groupant les données et les traitement poches les uns des autres
- Réduire [[Glossaire général#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 général#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 [[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 [[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 général#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 général#Méthode|méthode]] une séquence d'instructions et peut ainsi encapsuler **des données** et **du comportement réutilisable**.
La [[Glossaire général#Signature de méthode|signature d'une méthode]] définit son **[[Glossaire général#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 général#Jar|jars]] sera approfondi dans [[Maven|le module consacré à la gestion des dépendances]].
## Modificateurs de visibilité
Les [[Glossaire général#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 général#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 général#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 général#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 général#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 général#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
## Exercices - Les méthodes et visibilité
Une méthode en Java est un bloc de code qui effectue une tâche spécifique.
Elle est définie au sein d'une classe et peut être appelée pour exécuter
une action sur des données contenues dans des objets de cette classe.
Les méthodes sont utilisées pour organiser et structurer le programme en
unités fonctionnelles, rendant ainsi le code plus modulaire et réutilisable.
### Exercices
Réalisez les exercices suivants (vous ne pouvez pas utiliser les boucles,
les conditions ou toute autre possibilité algorithmique de java).
Vous pouvez utiliser les variables, les attributs et les méthods et tout ce qui peut s’y associer).
### 1 - Addition
Crée une méthode `calculerSomme(int a, int b)` dans une classe `Addition`.
La méthode doit simplement additionner les deux paramètres passés arguments de
la méthode et retourner le résultat.
### 2 - Personne (visibilité)
Crée une classe `Personne` avec les méthodes suivantes :
- Une méthode `afficherNom()` qui affiche le nom de la personne.
Cette méthode doit être publique.
- Une méthode `changerNom(String nom)` qui permet de changer le nom de la personne.
Cette méthode doit être **privée**.
- Une méthode `afficherAge()` qui affiche l'âge de la personne.
Cette méthode doit être **protégée**.
- Une méthode `afficherAdresse()` qui affiche l'adresse de la personne.
Cette méthode doit avoir aucun modificateur (c'est-à-dire `default`).
Ensuite, dans la classe principale, crée une instance de `Personne` et appelle les méthodes publiques et par défaut
Dans une autre classe, crée un objet `Personne` et teste les méthodes
selon leur visibilité et observe le résultat.
### 3 - Calculatrice (surcharge)
Créer une classe `Calculatrice` avec des méthodes pour effectuer
l'addition, la soustraction, la multiplication et la division.
Vous devez utiliser la surcharge de méthode.
- La classe **ne doit pas utiliser de conditions** (if, else) **ni de boucles**.
- L'entrée des données sera simplifiée et prédéfinie, et les calculs devront être effectués en utilisant des méthodes directement appelées.
- `add()`, `sous()`, `divid()`, `multi()` prennent deux entiers en paramètres et retourne leur somme.
- `add()`, `sous()`, `divid()`, `multi()` prennent deux nombres à virgule flottante (double) en paramètres et retourne leur somme.
- public double `effectuerOperation(String operation, double a, double b)` sera la méthode qui permettra de réaliser les opération elle poura utiliser la condition Switch exceptionnellement. Seul cette méthode sera appeler depuis l’instance `Calculatrice` pour effectuer des additions, soustractions, divisions et multiplications.
- Un message secret (easter egg) doit être affiché lorsqu'une certaine operation est détecté, sans utiliser de conditions explicite.
### 4 - Compteur (static)
Crée une classe `Compteur` qui contient :
- Une méthode statique `incrementer(int valeur)` qui prend un entier en paramètre et l'ajoute à une variable statique compteur.
- Une méthode statique `afficherCompteur()` qui affiche la valeur actuelle du compteur.
Que pensez-vous de ce compteur ?
Est-ce que cela pourrait poser des problèmes ?
## À suivre
[[Héritages en Java]]