2. Abstraction et encapsulation

2.1. Abstraction

L’abstraction est le processus qui consiste à représenter des objets qui appartiennent au monde réel dans le monde du programme que l’on écrit. Il consiste essentiellement à extraire des variables pertinentes, attachées aux objets que l’on souhaite manipuler, et à les placer dans un modèle informatique convenable. Supposons que l’on veuille écrire un programme qui gère des maisons. Si l’on se place du point de vue de celui qui l’habite, on s’intéressera probablement au nombre de pièces, à leurs surfaces, si elle est proche des commerces, si elle est accessible par les transports en commun. Celui qui la construit devra connaître les délais de construction, avoir le permis de construire et les plans, avoir des détails sur la façon de la connecter aux différents réseaux : égouts, eau, électricité, téléphone, etc… Du point de vue de la municipalité qui a besoin de calculer ses impôts locaux, il faudra connaître la surface, la date de construction, l’implantation locale, etc… Une même notion réelle peut donc donner différentes abstractions informatiques, toutes construites en fonction du problème posé. Toutes ces données doivent donc être regroupées ensemble dans une structure commune. La liste des données qui sera retenue variera avec l’application que l’on doit traiter. On appelle cette phase d'analyse "l'analyse métier", et les abstractions qui en découlent le "domaine métier". Lorsque l'on écrit un logiciel qui fait des choses (ce n'est pas toujours le cas...), on définit toujours le "domaine métier", et les objets de ce domaine. La construction d'un modèle objet suit des règles. Certaines sont des règles systématiques, d'autres sont plus empiriques. Le fait de disposer d'un injecteur de dépendances, de s'imposer une bonne testabilité du code que l'on écrit, que ce soit unitairement ou à plus haut niveau a un impact sur la façon dont on construit ces classes métier ou techniques. Nous verrons ces règles dans la suite de ce document.

2.2. Encapsulation

La première étape du travail de conception a consisté à définir les données intéressantes, et à les regrouper dans des structures qui ont un sens. La deuxième étape consiste à définir les méthodes d’accès à ces données, et les calculs qui seront effectués dessus. L’idée de la programmation objet est de regrouper ces méthodes d’accès et de calcul dans la même structure que les données. Le regroupement des données et des méthodes est un des points importants des langages objet, qui n’est absolument pas supporté dans des langages tels que le C, Pascal ou Fortran. C’est cela que l’on appelle l’encapsulation. Les opérations sur les types définis à l’avance sont en général des opérations arithmétiques tels que +, -, * et /. En Java, les opérations sur les types de données définis par l’utilisateur sont des méthodes. Il n’est pas possible de redéfinir les opérateurs de base pour les faire agir sur des types de données autres que ceux pour lesquels ils sont prévus, à la différence du C++. La communauté Java réfléchit activement à cet aspect, et il est possible que cette fonctionnalité apparaisse à l’avenir. Ce genre de chose doit être utilisé avec beaucoup de précautions, dans la mesure où il devient difficile, une fois qu’un code a été écrit, de savoir quel type d’opération est réellement effectué à quel moment. La seule exception à cette règle est la possibilité d'utiliser l'opérateur + pour concaténer les chaînes de caractères.
Java langage & API
Retour au blog Java le soir
Cours & Tutoriaux
Table des matières
Introduction : un peu d'histoire
1. Java : genèse d'un nouveau langage
Programmer en Java
1. Un premier exemple
1.1. Aperçu général, cycle de vie
1.2. Un premier programme
1.3. Programmes, applets, servlets, etc...
2. Une première classe
2.1. Écriture d'une classe
2.2. Instanciation de cette classe
3. Types de base, classes et objets
3.1. Types de base
3.2. Classes et objets
Classes Object et String
1. Introduction
2. La classe Object
2.1. La méthode toString()
2.2. La méthode clone()
2.3. La méthode equals()
2.4. La méthode hashCode()
2.5. La méthode finalize()
2.6. La méthode getClass()
3. La classe String
3.1. Introduction
3.2. Construction d'un objet de type String
3.3. Concaténation, StringBuffer et StringBuilder
3.4. Concaténations de chaînes de caractères depuis Java 8
3.5. Concaténations de chaînes de caractères depuis Java 11
3.6. Extraction d'une sous-chaîne de caractères
3.7. Comparaison de deux chaînes de caractères
3.8. Méthodes de comparaisons lexicographiques
3.9. Méthode de recherche de caractères
3.10. Méthode de modification de chaîne
3.11. Méthode de duplication
3.12. Support de l'unicode, internationalisation
Structure d'une classe
1. Introduction
2. Classes
2.1. Classes publiques
2.2. Classes internes
2.3. Classe membre
2.4. Classes locales
2.5. Classes anonymes
2.6. Le mot-clé this
3. Éléments statiques
3.1. Champ statique
3.2. Cas des constantes
3.3. Bloc statique
3.4. Classe membre statique
4. Membres d'une classe, visibilité
4.1. Bloc non statique
4.2. Accès à un membre, visibilité
4.3. Les champs
4.4. Signature d'une méthode
4.5. Les méthodes
4.6. Getters et Setters
5. Constructeur, instanciation
5.1. Chargement d'une classe
5.2. Constructeurs d'une classe
5.3. Instanciation d'un objet
5.4. Destruction d'objets
5.5. Le mot-clé final
6. Énumérations
6.1. Déclaration d'une énumération
6.2. Classe énumération
6.3. Méthode toString()
6.4. Méthode valueOf()
6.5. Méthode values()
6.6. Méthode ordinal()
6.7. Méthode compareTo()
6.8. Constructeurs privés
6.9. Classe utilitaire : EnumSet
Noms, opérateurs, tableaux
1. Introduction
2. Identificateurs, noms et expressions
2.1. Identificateurs et noms
2.2. Expressions
3. Opérateurs, ordre d'exécution
3.1. Ordre d'exécution
3.2. Les opérateurs
3.3. Les opérateurs ++ et --
3.4. Les opérateurs % et /
3.5. Les opérateurs <<, >> et >>>
3.6. L'opérateur instanceof
3.7. Les opérateurs &, | et ^
3.8. Les opérateurs && et ||
3.9. L'opérateur ? ... :
3.10. Les opérateurs d'affectation
4. Tableaux
4.1. Création d'un tableau
4.2. Initialisation d'un tableau
4.3. Utilisation d'un tableau comme un Object
4.4. Tableaux de tableaux
4.5. Copie de tableaux
5. Blocs, boucles et contrôles
5.1. Blocs
5.2. Mots-clés réservés
5.3. Tests : if et switch
5.4. Boucles : for, while, do ... while
5.5. Commandes continue et break
5.6. Commandes return et goto
Nombres, précision, calculs
1. Introduction
2. Calculs
2.1. Précision
2.2. Codage des nombres flottants
2.3. Le mot-clé strictfp
2.4. Conversion de types
3. Dépassements de capacité
3.1. Cas des entiers
3.2. Cas des flottants
3.3. Bibliothèques BigInteger et BigDecimal
4. Fonctions mathématiques
4.1. Fonctions usuelles
4.2. Générateurs aléatoires
5. Classes enveloppe
5.1. Associer les types de base à des objets
5.2. Auto-boxing
Héritage, abstraction, interfaces
1. Introduction
2. Abstraction et encapsulation
2.1. Abstraction
2.2. Encapsulation
3. Héritage
3.1. Définition de l'héritage
3.2. Conséquences pour les membres
3.3. Polymorphisme
3.4. Empêcher l'héritage
4. Classes abstraites
5. Interfaces
5.1. Introduction
5.2. Définition
5.3. Java 8 et les interfaces
5.4. Utilisation des interfaces
5.5. Définition de constantes dans les interfaces
5.6. Utilité des interfaces
Packages
1. Introduction
2. Notion de paquet
2.1. Déclaration d’appartenance à un paquet
2.2. Chargement d’une classe
2.3. Choix de nom
3. Archives, chemin de recherche, classpath
3.1. Archives
3.2. Variable CLASSPATH
3.3. Notion de classloader
3.4. Bilan sur les classes chargées
3.5. Visibilité
3.6. Conseils d'écriture, bibliothèque standard
Exceptions
1. Introduction
2. Erreurs et Exceptions
2.1. Classe Throwable, notion de stack trace
2.2. Classe Error
2.3. Classe RuntimException
2.4. Classe Exception
3. Déclenchement d'une exception
3.1. Exceptions déclenchées par la JVM
3.2. Exceptions déclenchées par l'application
4. Capter une exception
4.1. Traiter une exception localement
4.2. Code de captage
5. Créer ses propres exceptions
Entrées / sorties
1. Introduction
2. Notion de fichier
2.1. Introduction
2.2. La classe File
2.3. Construction d'une instance de File
2.4. Méthodes exposées
3. Flux de sortie
3.1. Introduction, notion de flux
3.2. Écriture de caractères, classe Writer
3.3. Bufferisation, construction d'un flux sur un autre
3.4. Utilisation de PrintWriter
3.5. Écriture d'octets, OuputStream
3.6. Écriture de types primitifs : DataOutputStream
3.7. Écriture d'objets : ObjectOutputStream
4. Flux d'entrée
4.1. Introduction
4.2. Lecture de caractères, classe Reader
4.3. Bufferisation, lecture ligne par ligne
4.4. Lecture d'octets : InputStream
4.5. Lecture de types primitifs : DataInputStream
4.6. Lecture d'objets : ObjectInputStream
5. Lecture et écriture de flux croisés
5.1. Introduction
5.2. Lire des caractères sur un flux binaire : classe InputStreamReader
5.3. Écrire des caractères sur un flux binaire : classe OutputStreamWriter
5.4. Remarque sur les jeux de caractères
6. Serialization d'objets
6.1. Enjeu de la sérialization d'objets
6.2. Serialization d'un objet
6.3. Sérialization d'une grappe d'objets
6.4. Première surcharge : méthode writeObject() readObject()
6.5. Deuxième surcharge : utilisation d'un externalizer
6.6. Troisième surcharge : utilisation d'un objet proxy
7. Flux compressés
7.1. Introduction
7.2. Flux de type gzip
7.3. Flux de type zip