Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

Introduction

Vocabulaire de la POO

  • Objet
  • Instance
  • Classe
  • Attributs
  • Méthodes

Les notions principales

La classe

  • Client
  • Nom
  • Prénom
  • Numéro
  • Construire client
  • Calcul réduction

Les objets (ou instances)

  • M. Durand : Client
  • Durand
  • Jean
  • 123456
  • Mme Dupond : Client
  • Dupond
  • Christine
  • 654321

Relations entre les classes

Relation Équivalent Exemple
Dépendance utilise Commande va utiliser Client afin de savoir si le compte est suffisamment crédité. En revanche, Client ne dépend pas de Commande
Agrégation possède Une Commande possède ou contient des instances de Produit
Héritage est Une CommandeSpeciale est une (ou hérite de) Commande. Toutes les données et comportements de Commande sont passés à CommandeSpeciale. CommandeSpeciale peut définir de nouvelles données et méthodes ou redéfinir des comportements dont elle a hérité.

Comparaison avec la programmation procédurale

Programmation procédurale

  • Identification des tâches et découpage en sous-tâches
  • Écriture de procédures pour résoudre ces tâches
  • Convient pour des problèmes simples
  • Données globales

 

Programmation orientée objet

  • Identification des objets-métier en classes
  • Définition des méthodes dans chaque classe responsable
  • Permet de modéliser des problèmes plus complexes
  • Données protégées (principe de responsabilité)
rotation(forme, typeForme){
  if(typeForme == "Carré") {
    rotationCarre(forme);
  } else if(typeForme == "Rond") {
    //On ne fait rien
  } else if(typeForme == "Triangle") {
    rotationTriangle(forme);
  }
}

rotationCarre(forme) {...}
rotationTriangle(forme) {...}
class Forme {
  void rotation() {}
}

class Carre extends Forme {
  void rotation(){ /* Rotation Carre*/ }
}

class Rond extends Forme {
}

class Triangle extends Forme {
  void rotation(){ /* Rotation Triangle*/ }
}

La notion de référence

String chaineNonInitialisee;

String chaineNull = null;


String chaineVide = "";
String chaineVide = new String("");


String chaine = "Bonjour";
chaine = null;

Les classes standard

  • String
  • Math
  • Classes enveloppes
  • Collections

La classe String

La classe Math

Opération Méthode retour Exemple
Arrondi round(float ou double) int ou long
ceil(double) double
floor(double) double
Math.round(4.56); //5
Math.ceil(4.23);//5
Math.floor(5.56);//5
Puissance pow(double base, double exposant) double
Math.pow(2, 3);//8
Minimum/Maximum min(numeric, numeric) numeric
max(numeric, numeric) numeric
Math.min(4,5);//4
Math.max(4,5);//5
... ... ...

Classes enveloppes

  • booleanBoolean
  • charCharacter
  • byteByte
  • shortShort
  • intInteger
  • longLong
  • floatFloat
  • doubleDouble
  • Boolean.logicalXor(a, b); //Ou exclusif logique entre deux booléens
  • Character.isDigit('5');//true; Test si le caractère est chiffre
  • Byte.decode("0x6b");//107; Décodage de valeurs hexadécimales
  • Short.parseShort("5");//Renvoie le Short 5
  • Integer.max(4, 5);//5
  • Long.numberOfTrailingZeros(500);//2
  • Float.isNaN(Float.POSITIVE_INFINITY - Float.POSITIVE_INFINITY);//true
  • Double.isInfinite(Double.NEGATIVE_INFINITY / 0.0);//true

Autoboxing et Unboxing

Integer monInteger = 127;
monInteger += 1;
Integer monInteger = 128;
Integer monInteger2 = 128;

monInteger <= monInteger2;
monInteger == monInteger2;
monInteger.equals(monInteger2);
Integer monInteger = 127;
Integer monInteger2 = 127;

monInteger == monInteger2;

Les collections

Les listes ArrayList

ArrayList<String> noms = new ArrayList<>();
noms.add("Jean");//[ "Jean" ]
noms.add(0, "Pierre"); //[ "Pierre", "Jean" ]
noms.addAll(Arrays.asList("Simon", "Jacques"));//[ "Pierre", "Jean", "Simon", "Jacques"])
noms.isEmpty();//false
noms.contains("Simon");//true
noms.indexOf("Pierre");//0
noms.size();//4
noms.get(2);//"Simon"
noms.remove(1);//[ "Pierre", "Simon", "Jacques"])
noms.remove("Pierre");//[ "Simon", "Jacques"])
noms.sort(String::compareTo);//Notation Java 8 [ "Jacques", "Simon"])
noms.sort(new Comparator<String>() {
    public int compare(String o1, String o2) {
        return o1.compareTo(o2);
    }
});//Notation Java < 8 [ "Jacques", "Simon"])
for (String prenom : noms){
    System.out.println(prenom);
}

Les ensembles HashSet

HashSet<String> setPrenoms = new HashSet<>();

setPrenoms.add("Jean");//[ "Jean" ]
setPrenoms.add("Jean");//N'a aucun effet car l'item est déjà présent !
setPrenoms.add("Pierre");//[ "Pierre", "Jean" ]]
setPrenoms.addAll(Arrays.asList("Simon", "Jacques"));//[ "Pierre", "Jean", "Simon", "Jacques"])
setPrenoms.isEmpty();//false
setPrenoms.contains("Simon");//true
setPrenoms.size();//4
setPrenoms.remove("Pierre");//[ "Jean", Simon", "Jacques"])

for (String prenom : setPrenoms){
    System.out.println(prenom);//L'ordre d'affichage est potentiellement différent de l'ordre d'insertion
}

Les tables de hachage HashMap

HashMap<Integer, String> mapNombres = new HashMap();

mapNombres.put(1, "Un");//[ 1 => "Un" ]
mapNombres.put(3, "Trois");//[ 1 => "Un", 3 => "Trois"]
mapNombres.put(2, "DEUX");//[ 1 => "Un", 3 => "Trois", 2 => "DEUX" ]
mapNombres.put(2, "Deux");//[ 1 => "Un", 3 => "Trois", 2 => "Deux" ]
mapNombres.putIfAbsent(2, "AAA");//[ 1 => "Un", 3 => "Trois", 2 => "Deux" ]
mapNombres.isEmpty();//false
mapNombres.containsKey(2);//true
mapNombres.containsValue("Un");//true
mapNombres.size();//3
mapNombres.remove(2);//[ 1 => "Un", 3 => "Trois"]

for (Integer n : mapNombres.keySet()){
    System.out.println(mapNombres.get(n));//Affiche "Un" et "Trois"
}

Créer ses propres classes

  • Définir son nom et la placer dans un package
  • Définir ses attributs et ses relations d'agrégation
  • Implémenter un ou plusieurs constructeurs
  • Implémenter des méthodes
  • Gérer la visibilité des attributs et des méthodes

La notion de package

package com.ipiecoles.java.java220;

import java.util.Date;

import java.io.*;


import static java.lang.System.out;

public class Exemple {
  Date dateJava;
  java.sql.Date dateSql;
  File fichier;
  void bonjour(){
    out.print("Bonjour !");
  }
}

Les attributs

  • Commande
  • Prochain Numéro
  • Numéro
  • Client
  • Priorité
  • Items
  • Est réglée ?
  • ...
class Commande {

  static long prochainNumero = 1L;

  final Long numero;

  Client client;

  int priorite;

  HashMap<Integer, Item> items;

  Boolean estReglee = false;

}

Les méthodes

  • Commande
  • Calcul d'un délai de livraison
  • Régler une commande
  • Ajouter un item
  • ...
class Commande {
  static Integer calculDelaiLivraison(int priorite){
    //Livraison plus rapide en fonction de la priorité
    return priorite == 1 ? 3 : 5;
  }

  void reglerCommande(Double montant) {
    //Réglement de la commande
    this.montantRegle -= montant;
    this.client.metAJourSolde(montant);
  }

  void ajouterItem(Item item) {
    //Ajout d'une item dans la map
    this.items.put(item.getId(), item);
  }
}

Les constructeurs

Commande(){
}

Commande(Long numero, Client client) {
  this.numero = numero;
  this.client = client;
}

Commande(Long numero, Client client, int maPriorite) {
  this(numero, client);
  priorite = maPriorite;
}

Commande c = new Commande();

c = new Commande(12345L, new Client());

Visibilité

Modificateur Effet Utilisation
private Visible uniquement par la classe Attributs des classes, méthodes internes
public Visible par toutes les classes Constructeurs (!), getters et setters (pour les champs pouvant être manipulés), constantes, méthodes en lecture seule ou devant être utilisées en dehors de la classe.
protected Visible par toutes les sous-classes et tout le package Sauf cas particulier, ne pas déclarer les attributs en protected. En revanche les méthodes protégées sont plus courantes.
(par défaut) Visible par tout le package Éviter de ne pas spécifier la visibilité d'une méthode ou d'un attribut !

Encapsulation

public class Bonjour {
  public static final String BASE_MESSAGE = "Bonjour" ;
  private String nom;
  private Date dateCourante;

  public Bonjour(String nom){
    this.nom = nom;
    this.dateCourante = new Date();
  }
  public void ditBonjour(){ out.println(formaterMessage()); }
  private String formaterMessage(){ return BASE_MESSAGE + " " + this.nom; }

  public String getNom() { return nom; }
  public void setNom(String nom) { this.nom = nom; }
  public Date getDateCourante() { return dateCourante; }
}

Héritage

public class Client {
  private long numero;
  private double solde;
  private String adresseLivraison, adresseFacturation;

  public Client(long numero, double solde, String adresseLivraison, String adresseFacturation) {
    this.numero = numero; this.solde = solde;
    this.adresseLivraison = adresseLivraison;
    this.adresseFacturation = adresseFacturation;
  }
  public final double calculMontant(double montantHT){
    return montantHT * tauxTva();
  }
  protected double tauxTva(){
    return 1.2;//Par défaut on paye avec 20% de TVA
  }
}

public class Professionnel extends Client {
  private String raisonSociale;
  private String siret;

  public Professionnel(long numero, double solde, String adresseLivraison, String adresseFacturation, String raisonSociale, String siret) {
    super(numero, solde, adresseLivraison, adresseFacturation);
    this.raisonSociale = raisonSociale; this.siret = siret;
  }
  protected double tauxTva(){
    return 1.0;//Les pros payent en HT
  }
}

Hiérarchie d'héritage et classe Object

  • Object

  • equals


  • hashCode


  • toString

  • ...
class Client {
...
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null) return false;
    if (getClass() != o.getClass()) return false;
    Client c = (Client) o;
    return numero == c.numero &&
      Double.compare(c.solde, solde) == 0 &&
      Objects.equals(adresseLivr, c.adresseLivr) &&
      Objects.equals(adresseFact, c.adresseFact);
  }

  public String toString() {
    return "Client{" +
      "numero=" + numero + ", solde=" + solde +
      ", adresseLivr='" + adresseLivr + '\'' +
      ", adresseFact='" + adresseFact + '\'' +
      '}';
    }
}

Polymorphisme

Boolean estClient, estProfessionnel, estObject;
Client c; Professionnel p;

c = new Client();
estClient = c instanceof Client; //true
estObject = c instanceof Object; //true (toujours...)

c = new Professionnel();
estClient = c instanceof Client; //true
estProfessionnel = c instanceof Professionnel; //true

p = new Professionnel();
estClient = p instanceof Client; //true
estProfessionnel = p instanceof Professionnel; //true

p = new Client();//Erreur de compilation

Exemple d'usage du polymorphisme

Client c = new Client();
Professionnel p = new Professionnel();
Client[] clients = new Client[2];
Professionnel[] pros = new Professionnel[1];

clients[0] = c; clients[1] = p;
pros[0] = p;

Boolean txTva = p.tauxTva() == clients[1].tauxTva();//true
Client[] clientsPros = pros;//OK
clientsPros[0] = new Client();//Erreur à l'exécution

ArrayList<Object> objects = new ArrayList();
objects.add(c); objects.add(p);
objects.add(new Integer(5));
objects.get(1).tauxTva()//Erreur de compilation

((Client)objects.get(1)).tauxTva(); //OK
((Professionnel)objects.get(1)).tauxTva(); //OK
((Professionnel)objects.get(0)).tauxTva(); //Erreur à l'exécution

Surcharge et redéfinition

public class Client {
  //Surchages
  public void ajouterItem(Item item) {
    ...
  }
  public void ajouterItem(String nom, int quantite){
    ...
  }

  //Redéfinition
  public String toString(){
    super.toString() + ...;
  }
}

Classes abstraites

public abstract class Client {
  private long numero;
  public Client(long numero) {
    this.numero = numero;
  }
  public double calculMontant(double montantHT){
    return montantHT * tauxTva();
  }
  public abstract double tauxTva();
}
public class Professionnel extends Client {
  private String raisonSociale;
  public Professionnel(long numero, String raisonSociale) {
    super(numero);
    this.raisonSociale = raisonSociale;
  }
  public double tauxTva(){
    return 1.0;//Les pros payent en HT
  }
}





public class Particulier extends Client {
  private String nom;
  public Particulier(long numero, String nom) {
    super(numero);
    this.nom = nom;
  }
  public double tauxTva(){
    return 1.2;//Les particuliers payent en TTC
  }
}

Bonnes pratiques

  • Mettre les attributs et méthodes communs dans la superclasse.
  • Ne pas utiliser protected sur les attributs et bien réfléchir si c'est utile lors de l'utilisation sur une méthode.
  • Utiliser l'héritage que lorsqu'il y a une relation d'appartenance est.
  • Ne pas utiliser l'héritage à moins que toutes les méthodes et attributs aient du sens pour les sous-classes.
  • Ne pas modifier le comportement attendu d'une méthode lors de sa redéfinition
  • Utiliser le polymorphisme à la place de tests instanceof

Classes final

final class CommandeSpeciale extends Commande {
  ...
}

public class CommandePlusSpeciale extends CommandeSpeciale { //Erreur de compilation

}

Classe générique

public class Paire<T, U> {
  private T premier;
  private U second;

  public Paire(T premier, U second) {
      this.premier = premier;
      this.second = second;
  }




  public U getSecond() { return second; }
  public T getPremier() { return premier; }
  public void setSecond(U second) { this.second = second; }
  public void setPremier(T premier) { this.premier = premier; }
}
Paire<String, Integer> p = new Paire<String, Integer>("Un", 1);
Paire<String, Integer> p = new Paire<>("Un", 1);//Java 7+
String s = p.getPremier();
p.setSecond(1);

Paire<String, Integer> p2 = new Paire("Un", 1);//Warning
p2.setPremier(1);//Erreur de compilation

Paire<String, Integer> p2 = new Paire(5, false);//Warning
Integer i = p2.getSecond();//ClassCastException

Paire p3 = new Paire("Un", 1);//Warning
p3.setPremier(false);//Warning
        

Méthodes génériques

public class ArrayIpi {
  public static <T> T getMiddle(T[] a)
  {
    return a[a.length / 2];
  }

  public static <T> T min(T[] a) {
    if(a == null || a.length == 0) {
      return null;
    }
    T min = a[0];
    for (int i = 1; i < a.length; i++){
      if(min.compareTo(a[i]) > 0){
          min = a[i];
      }
    }
    return min;
  }
}

    String[] noms = {"Jean", "Pierre", "François"};
    String milieu = ArrayIpi.<String>getMiddle(noms);
    String milieu = ArrayIpi.getMiddle(noms);
    ArrayIpi.min(noms);//François
          

Interfaces

public interface Client {
  public static final double PRIX_BASE = 1.0;
  public abstract double tauxTva();
  public default void affichePrixBase(){
    System.out.println("Prix de base : " + PRIX_BASE);
  }
}

public class Particulier implements Client {
  public double tauxTva(){
    return PRIX_BASE + 0.2;
  }
}

Client client = new Particulier();//OK
Client client2 = new Client();//Erreur de compilation

Implémentations multiples

public interface Comparable<T> {
  int compareTo(T o);
}

public class Particulier implements Client, Comparable<Client> {
  private double solde;
  public Particulier(double solde) { this.solde = solde; }
  public int compareTo(Client o) {
    return Double.compare(solde, o.solde);
  }
  public double tauxTva(){
    return 1.2;
  }
}

Particulier[] clients = new Particulier[3];
clients[0] = new Particulier(3500.0);//Client 1
clients[1] = new Particulier(6500.0);//Client 2
clients[2] = new Particulier(5500.0);//Client 3
Arrays.sort(clients);//Client 1, 3, 2

Classes internes

  • Elles ne sont pas visibles des autres classes du package de la classe externe.
  • Les méthodes des classes internes peuvent accéder aux attributs et méthodes de la classe interne (même s'ils sont private).
  • C'est ce mécanisme qui est utilisé dans les classes anonymes
  • Lors de l'instanciation d'un objet d'une classe interne, l'objet de la classe externe qui lui a donné naissance lui est systématiquement associé.
public class Commande {
    private List<Item> items;
  private double tva = 1.2;
  public void ajouterItem(String nm, int qte, double px) {
    Item item = new Item();
    item.nom = nm;
    item.qte = qte;
    item.prix = px;
    items.add(item);
  }
  private class Item {
    private int qte;
    private double prix;
    private String nom;
    public double prixItem(){ return qte * prix * tva; }
  }
  public double prixTotal(){
    return items.stream().map(Item::getPrixLigne)
      .reduce(0d, Double::sum);
  }
}
...
Commande commande = new Commande();
Commande.Item item = commande.new Item();

Classes internes locales

public class Item {
  private String nom;
  private int quantite;
  private double prix;

  public void afficheItem(){
    final String AFFICHAGE = "Affichage de l'item : ";
    boolean accessibleAfficheur = false;
    class Afficheur {
      private String texte;
      public Afficheur() {
        this.texte = AFFICHAGE + nom + ", qte:" + quantite + ", prix:" + prix;
      }
      public void affiche(){ System.out.println(texte); }
    }
  }
}
new Item("Produit", 5, 12.0).afficheItem();
//"Affichage de l'item : Produit, qte: 5, prix: 12.0"

Les classes internes anonymes

public class Particulier implements Client, Comparable<Client> {

  private double solde;

  public Particulier(double solde) { this.solde = solde; }

  public int compareTo(Client o) {
    Comparator<Particulier> comparator = new Comparator<Particulier>() {
      public int compare(Particulier p1, Particulier p2) {
        return p1.solde.compareTo(p2.solde) ;
      }
    };
    return comparator.compare(this, o) ;
  }
}

Les lambdas

Comparator<Particulier> comparator = new Comparator<Particulier>() {
  public int compare(Particulier p1, Particulier p2) {
    return p1.getSolde().compareTo(p2.getSolde()) ;
  }
};

Comparator<Particulier> comparator = (Particulier p1, Particulier p2) -> o1.getSolde().compareTo(o2.getSolde());

Comparator<Particulier> comparator = (Particulier p1, Particulier p2) -> {
  Double s1 = o1.getSolde(); Double s2 = o2.getSolde();
  return s1.compareTo(s2);
});

Les références de méthodes

public class Particulier {
  private Long numero;
  private Double solde;
  public static int compareSolde(Particulier a, Particulier b) {
    return a.solde.compareTo(b.solde);
  }
}
...
public class ComparaisonClient {
  public int compareSolde(Particulier a, Particulier b) {
    return a.getSolde().compareTo(b.getSolde());
  }
}
...
public interface ParticulierFactory{
  public abstract getParticulier(Long numero, Double solde);
}
Particulier[] clients = { new Particulier(1L, 1200.0), ... };
//Référence à une méthode statique
Arrays.sort(particuliers, Particulier::compareSolde);

//Référence d'une méthode d'instance d'un objet spécifique
ComparaisonClient comp = new ComparaisonClient();
Arrays.sort(clients, comp::compareSolde);

//Référence de la méthode d'instance compareToIgnoreCase
//d'un objet spécifique du type particulier String
String[] myArray = {"one", "two", "three", "four"};
Arrays.sort(myArray, String::compareToIgnoreCase);



//Référence à un constructeur
ParticulierFactory partFactory = Particulier::new;
Particulier p = partFactory.getParticulier(123L, 250.0);

Les Streams

List<String> noms = Arrays.asList("pierre", "jean", "jeremy", "marc", "jennifer");
noms.stream()
 .filter(x -> x.contains("je"))

 .map(x -> x.substring(0, 1).toUpperCase() + x.substring(1))

 .sorted()

 // Affichage :
 // Jean
 // Jennifer
 // Jeremy
 .forEach( System.out::println );

List<Commande> commandes = ... ;

List<Client> clients = commandes.stream()
  .map( c -> c.getClient() )
  .collect( Collectors.toList() );