*Note : Les notions importantes sont dans la table des matières*
<!-- Table générée automatiquement par pandoc -->
# Partie POO (théorie)
## Objet
### Définition
Un objet est une entité qui possède des **attributs** et des **méthodes**. On peut le voir comme une boite noire qui contient des données et des fonctions.
#### Exemple
Une voiture est un objet qui possède des attributs comme la couleur, le nombre de portes, etc. et des méthodes comme `demarre` et `arrete`.
## Interface
### Définition
Une interface est un ensemble de méthodes qui n'ont pas de corps : on dit "Une voiture a la fonction démarre, mais on ne sait pas comment elle démarre". C'est en gros la liste des choses que peut faire un objet.
#### Exemple
On a une interface `Vehicule` qui contient les méthodes `demarre` et `arrete`.
### Implémentation
On dit qu'une classe **implémente** une interface si elle contient toutes les méthodes de l'interface.
#### Exemple
Si par exemple le code de `Voiture` contient toutes les méthodes de `Vehicule` : `demarre` et `arrete`, on dit que `Voiture` implémente `Vehicule`.
## Sous Typage
### Définition
Le sous-typage c'est une relation entre deux types pour dire : "Je suis l'enfant de ce type".
#### Exemple
Une voiture est un véhicule, donc une voiture est un sous-type de véhicule.
Il existe plusieurs types de sous-typage :
-**Sous-typage structurel** : On dit qu'un type est un sous-type d'un autre type si il a la même structure (structure ici c'est par exemple les attributs et les méthodes).
-**Sous-typage nominal** : On dit qu'un type est un sous-type d'un autre type si il est explicitement déclaré comme tel.
### Sous-typage par héritage
Le sous-typage par héritage est un sous-typage nominal : On dit explicitement qu'un type est un sous-type d'un autre type.
Dans ce cas, le parent est appelé **super-type** et l'enfant est appelé **sous-type**, et le super-type transmet toutes ses propriétés au sous-type.
### Sous-typage par interface
Le sous-typage par interface est un sous-typage structurel : On dit qu'un type est un sous-type d'un autre type si il a la même structure.
*Note : Une interface n'a pas d'attributs*
#### Exemple
On a une interface `Vehicule` qui contient les méthodes `demarre` et `arrete`.
On a une classe `Voiture` qui implémente l'interface `Vehicule`.
On a une classe `Moto` qui implémente l'interface `Vehicule`.
La `Voiture` et la `Moto` sont des sous-types de `Vehicule` car elles ont la même structure.
### Lien entre sous-typage et polymorphisme
Le polymorphisme c'est le fait de pouvoir utiliser un objet de type `Voiture` comme un objet de type `Vehicule`.
Le sous-typage permet le polymorphisme : Si on a une classe `Voiture` qui est un sous-type de `Vehicule`, on peut utiliser un objet de type `Voiture` comme un objet de type `Vehicule`.
On dit parle de **substituabilité** : On peut substituer un objet de type `Voiture` à un objet de type `Vehicule`.
**Attention** : ce n'est pas réciproque : on ne peut pas remplacer un objet de type `Voiture` par un objet de type `Vehicule` car on perdrait des informations.
# Partie Java (pratique)
## Classes et objets
### Définition
Une classe est un modèle qui permet de créer des objets. On peut voir une classe comme un plan pour construire des objets.
#### Exemple
On a une classe `Voiture` qui permet de créer des objets de type `Voiture`.
```java
classVoiture{
// ...
}
```
On dit qu'on **instancie** une classe pour créer un objet. On dit aussi qu'on **crée une instance** de la classe.
```java
Voiturev=newVoiture();
```
### Types
En Java, on a plusieurs types :
-**Primitifs** : `int`, `double`, `boolean`, etc.
-**Objets** : `String`, `Voiture`, etc. (ont une majuscule)
### Attributs
Les attributs sont des variables qui sont propres à chaque objet. On peut voir les attributs comme des données qui sont stockées dans l'objet.
#### Exemple
On a une classe `Voiture` qui a un attribut `couleur`.
```java
classVoiture{
Stringcouleur;
}
```
On peut accéder à l'attribut d'un objet avec le point `.`.
```java
Voiturev=newVoiture();
v.couleur="rouge";
```
### Méthodes
Les méthodes sont des fonctions qui sont propres à chaque objet. On peut voir les méthodes comme des fonctions qui permettent de manipuler les données de l'objet.
#### Exemple
On a une classe `Voiture` qui a une méthode `demarre`.
```java
classVoiture{
voiddemarre(){
// ...
}
}
```
On peut appeler une méthode d'un objet avec le point `.`.
```java
Voiturev=newVoiture();
v.demarre();
```
### Constructeur
Le constructeur est une méthode qui permet d'initialiser les attributs d'un objet.
#### Exemple
On a une classe `Voiture` qui a un constructeur qui prend en paramètre la couleur de la voiture.
```java
classVoiture{
Stringcouleur;
Voiture(Stringcouleur){
// On initialise l'attribut couleur avec la valeur du paramètre couleur
this.couleur=couleur;
}
}
```
On peut appeler le constructeur avec le mot clé `new`.
```java
Voiturev=newVoiture("rouge");
```
### Visibilité des attributs et méthodes
Les attributs et les méthodes peuvent avoir une visibilité. C'est une information qui permet de savoir si on peut accéder à l'attribut ou à la méthode depuis l'extérieur de la classe.
On a plusieurs visibilités :
-**private** : On ne peut accéder à l'attribut ou à la méthode que depuis l'intérieur de la classe.
-**public** : On peut accéder à l'attribut ou à la méthode depuis l'extérieur de la classe.
-**protected** : On peut accéder à l'attribut ou à la méthode depuis l'intérieur de la classe et depuis les classes qui héritent de la classe.
#### Exemple
On a une classe `Voiture` qui a un attribut `couleur` et une méthode `demarre`.
```java
classVoiture{
publicStringcouleur;
publicvoiddemarre(){
// ...
}
}
```
Ici, l'attribut `couleur` et la méthode `demarre` sont **publics** : on peut y accéder depuis l'extérieur de la classe.
```java
Voiturev=newVoiture();
v.couleur="rouge";
v.demarre();
```
#### Exemple
On a une classe `Voiture` qui a un attribut `couleur` et une méthode `demarre`.
```java
classVoiture{
privateStringcouleur;
publicvoiddemarre(){
// ...
}
}
```
Ici, l'attribut `couleur` est **privé** : on ne peut y accéder que depuis l'intérieur de la classe. Si on essaye d'y accéder depuis l'extérieur de la classe, on aura une erreur.
```java
Voiturev=newVoiture();
v.couleur="rouge";// Erreur : on ne peut pas accéder à l'attribut couleur depuis l'extérieur de la classe
```
#### Exemple
On a une classe `Voiture` qui a un attribut `couleur` et une méthode `demarre`.
```java
classVoiture{
protectedStringcouleur;
publicvoiddemarre(){
// ...
}
}
```
Ici, l'attribut `couleur` est **protégé** : on peut y accéder depuis l'intérieur de la classe et depuis les classes qui héritent de la classe.
```java
classVoitureElectriqueextendsVoiture{
publicvoiddemarre(){
couleur="rouge";// On peut accéder à l'attribut couleur car VoitureElectrique hérite de Voiture
}
}
```
### Méthodes et attributs statiques
Les méthodes et les attributs statiques sont des méthodes et des attributs qui ne sont pas propres à chaque objet mais qui sont communs à tous les objets de la classe.
#### Exemple
Un exemple classique est la constante `Math.PI` qui est une constante qui est commune à tous les objets de la classe `Math`.
```java
doublepi=Math.PI;
```
On peut accéder à une méthode ou un attribut statique avec le nom de la classe.
```java
NomDeLaClasse.nomDeLaMethode();
NomDeLaClasse.nomDeLAttribut;
```
On le déclare avec le mot clé `static`.
```java
classVoiture{
staticintnombreDeVoitures=0;
Voiture(){
nombreDeVoitures++;
}
}
```
### Méthodes et attributs finaux
Les méthodes et les attributs finaux sont des méthodes et des attributs qui ne peuvent pas être modifiés.
#### Exemple
Un exemple classique est la constante `Math.PI` qui est une constante qui ne peut pas être modifiée.
```java
Math.PI=3.14;// Erreur : on ne peut pas modifier la constante Math.PI
```
On le déclare avec le mot clé `final`.
```java
classVoiture{
finalintnombreDeRoues=4;
}
```
### Méthodes et attributs abstraits
Les méthodes et les attributs abstraits sont des méthodes et des attributs qui n'ont pas de corps : on dit "Une voiture a la fonction démarre, mais on ne sait pas comment elle démarre".
Ce seront les classes qui héritent de la classe qui implémenteront les méthodes et les attributs abstraits.
**Attention** : Seules les classes abstraites peuvent avoir des méthodes et des attributs abstraits.
#### Exemple
On a une classe `Voiture` qui a une méthode `demarre`.
```java
abstractclassVoiture{// On déclare la classe comme abstraite
abstractvoiddemarre();// Méthode abstraite
voidarrete(){// Méthode non abstraite
// On implémente la méthode arrete comme elle n'est pas abstraite
}
}
```
On a une classe `VoitureElectrique` qui hérite de `Voiture` et qui implémente la méthode `demarre`.
```java
classVoitureElectriqueextendsVoiture{
voiddemarre(){// On implémente la méthode demarre car elle est abstraite
// On implémente la méthode demarre
}
}
```
## Héritage
### Définition
La définition de l'héritage se trouve dans la partie théorique : [Sous-typage par héritage](#sous-typage-par-héritage).
### En Java
En Java, on utilise le mot clé `extends` pour déclarer qu'une classe hérite d'une autre classe.
On a une classe `Voiture` qui hérite de la classe `Vehicule`.
```java
classVoitureextendsVehicule{
// ...
}
```
## Super
Le mot clé `super` permet d'accéder aux attributs et aux méthodes de la classe parente.
#### Exemple
On a une classe `Voiture` qui hérite de la classe `Vehicule`. Un véhicule a une méthode `demarre`.
```java
classVoitureextendsVehicule{
voiddemarre(){
super.demarre();// On appelle la méthode demarre de la classe parente
}
}
```
#### Exemple
On peut aussi appeler le constructeur de la classe parente avec le mot clé `super`.
```java
classVoitureextendsVehicule{
Voiture(Stringcouleur){
super(couleur);// On appelle le constructeur de la classe parente
}
}
```
## Redéfinition
### Définition (lol)
La redéfinition c'est le fait de redéfinir une méthode de la classe parente dans la classe enfant. Cela permet de modifier le comportement de la méthode.
#### Exemple
On a une classe `Voiture` qui hérite de la classe `Vehicule`. Un véhicule a une méthode `demarre`. On redéfinit la méthode `demarre` dans la classe `Voiture`.
```java
classVoitureextendsVehicule{
@Override// On indique que la méthode est redéfinie
voiddemarre(){
// On redéfinit la méthode demarre
}
}
```
### Méthode `toString`
La méthode `toString` permet de définir comment un objet doit être affiché sous forme de chaîne de caractères.
#### Exemple
On a une classe `Voiture` qui hérite de la classe `Vehicule`. On redéfinit la méthode `toString` dans la classe `Voiture`.
```java
classVoitureextendsVehicule{
@Override// On indique que la méthode est redéfinie
StringtoString(){
return"Je suis une voiture";
}
}
```
Quand on affiche un objet de type `Voiture`, on affiche la chaîne de caractères retournée par la méthode `toString`.
```java
Voiturev=newVoiture();
System.out.println(v);// Affiche "Je suis une voiture"
```
### Méthode `equals`
La méthode `equals` permet de définir comment un objet doit être comparé à un autre objet.
#### Exemple
On a une classe `Voiture` qui hérite de la classe `Vehicule`. On redéfinit la méthode `equals` dans la classe `Voiture`.
```java
classVoitureextendsVehicule{
@Override// On indique que la méthode est redéfinie
booleanequals(Objecto){
if(oinstanceofVoiture){// On vérifie que l'objet est de type Voiture
// On regarder si les attributs sont égaux
// ...
returntrue;
}else{
returnfalse;
}
}
}
```
Quand on compare un objet de type `Voiture` avec un autre objet, on utilise la méthode `equals`.
```java
Voiturev1=newVoiture();
Voiturev2=newVoiture();
System.out.println(v1.equals(v2));
```
### Méthode `hashCode`
La méthode `hashCode` permet de définir comment un objet doit être transformé en un nombre.
#### Exemple
On a une classe `Voiture` qui hérite de la classe `Vehicule`. On redéfinit la méthode `hashCode` dans la classe `Voiture`.
```java
classVoitureextendsVehicule{
@Override// On indique que la méthode est redéfinie
inthashCode(){
returnInteger.hashCode(nombreDeRoues);// On transforme le nombre de roues en un nombre
}
}
```
**Attention** : On doit définir `hashCode` et `equals` en même temps, et de façon cohérente : si deux objets sont égaux, alors ils doivent avoir le même `hashCode`.
### Utilité de `hashCode` et `equals`
`hashCode` et `equals` sont utilisés par les collections pour savoir si un objet est déjà présent dans la collection.
- Dans une `ArrayList`, on utilise `equals` pour savoir si un objet est déjà présent dans la liste.
- Dans une `HashMap`, on utilise `hashCode` pour savoir si une clé est déjà présente dans la map.
**Note** : C'était à savoir dans l'examen de cette année dans la question 1.
## Interfaces
### Définition
La définition de l'interface se trouve dans la partie théorique : [Sous-typage par interface](#sous-typage-par-interface).
### En Java
En Java, on utilise le mot clé `implements` pour déclarer qu'une classe implémente une interface.
```java
interfaceNomDeLInterface{
// ...
}
classNomDeLaClasseimplementsNomDeLInterface{
// ...
}
```
#### Exemple
On a une interface `Vehicule` qui a une méthode `demarre`.
```java
interfaceVehicule{
voiddemarre();
}
```
On a une classe `Voiture` qui implémente l'interface `Vehicule`.
```java
classVoitureimplementsVehicule{
@Override
voiddemarre(){
// On implémente la méthode demarre
}
}
```
## Polymorphisme
### Définition
La définition du polymorphisme se trouve dans la partie théorique : [Lien entre sous-typage et polymorphisme](#lien-entre-sous-typage-et-polymorphisme).
### En Java
En Java, on utilise le polymorphisme pour pouvoir utiliser un objet de type `Voiture` comme un objet de type `Vehicule`.
#### Exemple
On a un objet de type `Voiture` qu'on stocke dans une variable de type `Vehicule`.
```java
Vehiculev=newVoiture();
```
On peut appeler les méthodes de `Vehicule` sur l'objet de type `Voiture`.
```java
Vehiculev=newVoiture();
v.demarre();
```
## Surcharge
La surcharge c'est le fait de définir plusieurs méthodes avec le même nom mais avec des paramètres différents.
#### Exemple
On a une classe `Voiture` qui a deux méthodes `demarre` : une méthode qui prend en paramètre un `int` et une méthode qui prend en paramètre un `String`.
```java
classVoiture{
voiddemarre(intvitesse){
// ...
}
voiddemarre(Stringcouleur){
// ...
}
}
```
## Classe génériques
### Définition
Une classe générique est une classe qui peut prendre en paramètre un type : une liste de `Voiture` ou une liste de `String`.
On la déclare avec le mot clé `class` suivi du nom de la classe et du type entre chevrons `< >`.
```java
classNomDeLaClasse<T>{
// T est le type passé en paramètre
// Puis on peut avoir des méthodes qui utilisent le type T :
voidmethode(Tparametre){
// ...
}
// "T" N'EST PAS CHANGÉ, ON MET "T" PARTOUT, on ne doit pas faire une classe par type
}
```
#### Exemple
On a une classe `Liste` qui peut prendre en paramètre un type `T`.
```java
classListe<T>{
// ...
}
```
## Outils
### Les listes
Une liste est une collection d'objets. On peut voir une liste comme un tableau qui peut grandir et rétrécir.
L'objet `List` est abstrait, il faut utiliser une classe concrète comme `ArrayList` ou `LinkedList`.
#### Exemple
On a une liste de `Voiture`.
```java
List<Voiture>voitures=newArrayList<Voiture>();
```
On a les méthodes suivantes :
| Méthode | Description | Exemple |
| --- | --- | --- |
| `add` | Ajoute un élément à la liste | `voitures.add(new Voiture());` |
| `get` | Récupère un élément de la liste | `Voiture v = voitures.get(0);` |
| `size` | Récupère la taille de la liste | `int taille = voitures.size();` |
| `remove` | Supprime un élément de la liste | `voitures.remove(0);` |
| `contains` | Vérifie si un élément est présent dans la liste | `boolean contient = voitures.contains(new Voiture());` |
### Les maps
Une map est une collection d'objets qui sont associés à une clé. On peut voir une map comme un dict en Python.
L'objet `Map` est abstrait, il faut utiliser une classe concrète comme `HashMap` ou `TreeMap`.
#### Exemple
On a une map qui associe des `String` à des `Voiture`.