L'encapsulation est une technique de programmation qui permet de cacher les détails d'implémentation d'un objet pour ses utilisateurs, ou l'état interne d'un système. Java donne plusieurs moyens pour assurer cette encapsulation, et il appartient au programmeur de les utiliser à bon escient. Afin d'empêcher l'utilisateur d'accéder directement aux champs de l'objet, on peut déclarer ses champs private et offrir éventuellement des méthodes de lecture ou d'écriture de ces champs, formés selon l'usage par get ou set (en français, ce pourrait être val ou chg) suivi du nom du champ capitalisé :
package geometrie; class Point { private double x, y; Point() {} Point(double x, double y) { this.x = x; this.y = y; } void setX(double x) { this.x = x; } void setY(double y) { this.y = y; } void getX() { return x; } void getY() { return y; } }
On doit alors remplacer, si p désigne un point :
private static double champMIN=0.0, champMAX=100.0; void setChamp(double champ) { if (champ < champMIN) this.champ = champMIN; else if (champ > champMAX) this.champ = champMAX; else this.champ = champ; }
Comme autre exemple, il y a des situations où le nombre de fois qu'un champ est modifié doit être limité (par exemple, la zone d'un lecteur de DVD peut être changée au plus 5 fois) : un champ supplémentaire, évidemment privé, et initialisé implicitement à 0, permet de contrôler le nombre de modifications.
private static final int N = 5; private int champModifié; void setChamp(int champ) { if (champModifié<N) this.champ = champ; champModifié++; }
Tous ces exemples constituent des patterns, c'est-à-dire des solutions typiques à des problèmes qui se rencontrent fréquemment, et qui peuvent être adaptées à chaque problème. La discipline d'encapsulation consiste à rendre systématiquement les champs privés, et à fournir, selon les besoins, l'une ou l'autre des méthodes d'accès setXxx et getXxx à chaque champ xxx, selon le pattern souhaité :
En outre, si le type est rendu public, les méthodes d'accès doivent également être déclarées publiques. Par exemple, pour des champs en lecture seulement :
package geometrie; public class Point { private double x, y; public Point() {} public Point(double x, double y) { this.x = x; this.y = y; } public void getX() { return x; } public void getY() { return y; } }
Loin d'être simplement un nouveau langage, Java est au cur d'une
nouvelle technologie, qui se déploie à la fois de façon matérielle
(futures cartes à puce, systèmes embarqués) et de façon logicielle sous
forme d'API spécialisée (Application Programming Interface), par
exemple pour l'accès aux bases de données, la programmation réseau ou
pour le graphique. L'utilisation des APIs fait que de nombreuses
applications traditionnellement difficiles à programmer deviennent très
simples. Cependant, leur utilisation demande une certaine compréhension
de leur organisation, qui résulte d'une part de traits du langage Java
(les packages, les interfaces, les règles
d'accessibilité, etc.) et d'autre part, de l'application systématique de
certaines méthodes de conception, qui identifient des situations
typiques et des façons de les aborder et de les résoudre. Le besoin de
recourir à de telles méthodes de conception n'est pas propre à
l'informatique. La notion de pattern a été
développée à la fin des années 1970 par un architecte, Christopher
Alexander, qui les définit ainsi :
«A pattern is a careful description of a perennial solution to a recurring problem within a building context, describing one of the configurations which brings life to a building.
A pattern language is a network of patterns that call upon one another. An individual house might, for example, call upon the patterns described under the names of half-hidden garden, light from two sides in every room, variation of ceiling height, bed alcove, etc. Patterns help us remember insights and knowledge about design and can be used in combination to create designs.»
Cette notion s'est vue réappropriée par des informaticiens, une dizaine d'années plus tard, et constitue actuellement l'une des approches les plus intéressantes de l'architecture des systèmes logiciels. Tant ces traits du langage que les patterns sont utiles à la programmation d'applications, pour peu que l'on s'efforce de les programmer proprement en respectant certains critères : indépendance de l'interface et de l'implémentation, facilité de modification ou de réutilisation, etc. Les choix que l'on fait quand on écrit un programme peuvent souvent se lire comme le choix d'un pattern contre un autre. En voici quelques autres : singleton, fabrication, itération, décoration, visitation (?), etc.
Une classe singleton est une classe qui ne peut avoir qu'une seule
instance. La réalisation d'une telle classe met en uvre :
class Singleton { A champ; // ... private static Singleton instance; private Singleton(A champ) { this.champ = champ; // ... } // ... static Singleton uniqueInstance(A champ) { if (instance == null) { instance = new Singleton(champ); } return instance; } }
Cette classe sera utilisée ainsi :
Singleton s1 = Singleton.uniqueInstance(new Double(2.3));
Remarquons que si la méthode uniqueInstance n'est pas appelée, l'instance n'est pas créée : dans une application donnée, cette classe a au plus une instance, elle peut n'en avoir aucune.
class Feu { static final Feu ROUGE = new Feu(); static final Feu ORANGE = new Feu(); static final Feu VERT = new Feu(); private Feu() {} }
Cette classe est conçue afin de vérifier les propriétés suivantes :