next up previous contents index
Next: Héritage et polymorphisme vertical Up: Panoramique et comparaison de Previous: Modularité

Cacher l'information

Dans les trois langages, on peut limiter l'accès aux variables d'instance et aux méthodes en utilisant les mots clefs suivants:

private
accessible seulement dans cette classe,
protected
accessible seulement dans cette classe et ses sous-classes,
public
accessible partout.

Cela donne un contrôle assez fin sur l'encapsulation.
Cependant, C++ et Java disposent aussi d'un quatrième niveau, qu'on appelle le niveau des friends. Cela revient à permettre l'accès aux données à toute classe, fonction ou méthode qui est un friend   (une amie), mais qui n'a aucune relation avec l'héritage. En C++ cela se fait en définissant explicitement à l'intérieur d'une classe les noms de ces privilégiés, comme dans
class ColorPoint: public Point {
private int color;
...
friend void antialias (ColorPoint c,ColorPoint d);
...
}

void antialias (ColorPoint c,ColorPoint d) { c->color=(c->color+d->color)/2; }

En C++, toute donnée est par défaut private, tandis qu'en Objective-C ell'est par défaut public et en Java accessible aux amis, mais à différence de C++, en Java on considère friend seulement les méthodes qui sont dans le même package.

Le choix du niveau d'accessibilité n'est pas facile: toute donnée déclarée private est effectivement invisible aux sous-classes, ce qui protège les sous-classes de tout changement apporté à la classe de base, mais cela signifie aussi que pour accéder à ces données les sous-classes doivent passer par une interface composée de méthodes, et cela nuit à l'efficacité. C'est là qu'on doit déjà commencer à choisir comment mélanger ADT et OO.
Un bon exemple de ce dilemme se retrouve dans un fragment de programme comme celui-ci:

class IntList {
??? int data[];
...
public hd { return data[0];}
...
}
class OrdIntList extends IntList {
...
public sortAscending { ??? }
}
Si on veut protéger l'implémentation de IntList, on ne pourra pas savoir que les données sont rangées dans un vecteur, ce qui nous empêchera d'utiliser un algorithme de tri efficace dans OrdIntList. Si par contre on ne la protège pas, on pourra être efficace dans OrdIntList, mais tout changement de représentation dans IntList se propagera aussi dans OrdIntList.
Dans ce cas spécifique, la meilleure solution semble être de garder l'implémentation protégée, et de fournir dans IntList des méthodes
public asVector: { // renvoie une repr\'esentation de la liste comme vecteur }
public fromVector: { // initialise la liste a partir d'un vecteur }
Ces méthodes donneront un accès efficace pour des opérations de tri, sans casser la barrière de modularité.


next up previous contents index
Next: Héritage et polymorphisme vertical Up: Panoramique et comparaison de Previous: Modularité

Roberto DiCosmo
Mon Jun 3 18:29:31 MET DST 1996