Source : lessoir.be
Formation Java / Spring Boot pour développeurs COBOL
À l’issue de cette journée, vous serez capable de :
List
Set
Map
En COBOL, il n’existe pas de mécanisme natif pour dire “Tout ce qui se prétend être un traitement de virement doit obligatoirement respecter ces règles” (enfin, je ne crois pas !)
On utilise alors :
Java introduit des interfaces, de l’Héritage et des classes abstraites pour rendre ces règles obligatoires et vérifiables par le compilateur.
J’ai conçu le cours de la manière suivante :
Dans ce cours, nous allons voir les notions importantes en POO à l’aide de diagramme de classe pour bien comprendre les relations d’héritage et l’implication qu niveau du code java, les mots-clés this et super. L’utilisation de instanceof. La différence entre agrégation, composition et héritage.
this
super
instanceof
Lien vers le cours Java sur l’héritage, polymorphisme,…
Lien vers les notions de Modificateur final, Classes abstraites, interfaces (Comparable, TreeSet)
Lien vers une explication simple de l’interface
Quelques TP
Héritage et polymorphisme
Vous avez déjà vu :
public class Compte { protected BigDecimal solde; }
Les classes qui héritent de Compte :
public class CompteCourant extends Compte { } public class CompteEpargne extends Compte { }
Et l’idée clé :
Compte c = new CompteCourant(...);
Dans ce code on va manipuler un objet du type parent, pas le type réel CompteCourant, c’est le polymorphisme !
Aujourd’hui, on va aller plus loin et plus proprement même si on l’a déjà vu dans la première partie.
Une classe abstraite :
Une classe abstraite est comparable à :
un COPYBOOK métier qui définit des règles communes, mais qui n’est jamais exécuté seul.
Pourquoi faire cela selon vous ?
On ne veut plus instancier un Compte sans que cela corresponde à quelque chose de concret !
Compte compte101 = new Compte(...)
Un compte doit toujours être soit de type :
Compte
Tranformons notre classe concrête Compte en classe abstraite avec le mot-clé abstract. Pour des raisons pédagogiques on ne va pas se préoccuper des vérifications et des exceptions.
abstract
public abstract class Compte { protected String numero; protected BigDecimal solde; public Compte(String numero, BigDecimal soldeInitial) { this.numero = numero; this.solde = soldeInitial; } public void crediter(BigDecimal montant) { solde = solde.add(montant); } // méthode abstraite public abstract void debiter(BigDecimal montant); public BigDecimal getSolde() { return solde; } }
Points importants :
debiter
Le CompteCourant hérite bien de la classe abstraites Compte et doit définir le code de la méthode debiter()
CompteCourant
debiter()
public class CompteCourant extends Compte { private BigDecimal decouvertAutorise; public CompteCourant(String numero, BigDecimal solde, BigDecimal decouvertAutorise) { super(numero, solde); this.decouvertAutorise = decouvertAutorise; } @Override public void debiter(BigDecimal montant) { BigDecimal futurSolde = solde.subtract(montant); if (futurSolde.compareTo(decouvertAutorise.negate()) < 0) { throw new IllegalStateException("Découvert dépassé"); } solde = futurSolde; } }
Le CompteEpargne hérite bien de la classe abstraites Compte et doit définir le code de la méthode debiter()
CompteEpargne
public class CompteEpargne extends Compte { public CompteEpargne(String numero, BigDecimal solde) { super(numero, solde); } @Override public void debiter(BigDecimal montant) { if (solde.compareTo(montant) < 0) { throw new IllegalStateException("Solde insuffisant"); } solde = solde.subtract(montant); } }
Une interface :
En réalité, il peut y avoir des spécificités que nous n’aborderons pas ici.
Une interface est comparable à une spécification fonctionnelle ou un contrat d’interface inter-applicative que plusieurs programmes doivent respecter.
DebitAutorise
public interface DebitAutorise { // une seule méthode dans cette interface void debiter(BigDecimal montant); }
Toute classe qui implémente cette interface s’engage à intégrer la méthode debiter (on parle d’implémenter), c’est-à dire de rédiger le code fonctionnel correspondant.
On utilise tout simplement le mot-clé implements pour dire à chacune des 2 classe qu’elles ont un contrat avec l’interface DebitAutorise.
implements
public class CompteCourant extends Compte implements DebitAutorise { } public class CompteEpargne extends Compte implements DebitAutorise { }
A ne pas confondre.
À partir de maintenant, on ne manipule plus UN compte, mais DES comptes, DES clients et DES opérations.
Les collections deviennent centrales, voire indispensables.
Utiles pour :
List<Compte> comptes = new ArrayList<>();
Le parcours polymorphique en supposant que nous avons plusieurs sous-types de Compte (Courant, Titre, Epargne et autres).
polymorphique
for (Compte c : comptes) { c.crediter(new BigDecimal("100")); }
Selon vous, quelle est la méthode qui sera appelée dans la boucle for ? Celle de Compte ? de CompteCourant ? de CompteEpargne ?…
Cette Collection permet d’éviter deux comptes avec le même numéro !
Set<String> numerosCompte = new HashSet<>();
numerosCompte.add("FR001"); numerosCompte.add("FR001"); // ignoré
Correspondance COBOL : contrôle d’unicité manuel et souvent tardif.
Cette collection facilite l’accès direct à un compte par son numéro.
Map<String, Compte> comptesParNumero = new HashMap<>();
comptesParNumero.put("FR001", compte1); Compte c = comptesParNumero.get("FR001");
Exemple :
List<Compte> comptes = new ArrayList<>(); comptes.add(new CompteCourant("FR001", new BigDecimal("1000"), new BigDecimal("500"))); comptes.add(new CompteEpargne("FR002", new BigDecimal("800"))); for (Compte c : comptes) { c.debiter(new BigDecimal("100")); System.out.println(c.getSolde()); }
if
polymorphisme
Consignes :
List<Compte>
for (Compte c : comptes) { c.debiter(new BigDecimal("50")); }
if (instanceof ...)
Aujourd’hui, vous avez :
Décisions structurantes :
Vous savez maintenant :
Le Jour 9 abordera :
```