Next: La nécessité du polymorphisme
Up: Héritage et polymorphisme vertical
Previous: Classes dont on aurait
Comment traiter de façon uniforme objets provenant de classes non reliés
Il arrive souvent d'avoir besoin de traiter de façon uniforme des objets de
classes en principe non reliées, mais qui savent tous répondre aux messages qui
leur seront envoyés dans un contexte précis. C'est par exemple le cas d'une
liste d'objets graphiques que l'on veut imprimer: on peut avoir des
rectangles et des cercles-colorés, tous capables de s'afficher en
répondant au message affiche, mais quel sera bien le type d'une liste de
ces objets? Une approche typique est de factoriser les messages communs dans une
classe artificielle (par exemple, graphicobject) que l'on rend ensuite
super-classe de toutes les classes dont les instances peuvent se retrouver dans
la même liste. Normalement, on ne pourra pas instancier graphicobject,
parce qu'il ne corresponde pas à des objets, mais à une abstraction
conceptuelle, et il faut donc du support pour vérifier que l'on ne prend pas
d'instances des classes abstraites.
En C++, cela se fait en déclarant la classe abstraite ou partie de ses
composantes comme virtual (cela étant quand même un gros hack, vu que
c'est aussi utilisé pour le contrôle de la liaison tardive), et en utilisant
cette classe comme super-type dans la liste.
au fait, une classe abstraite est une classe qui contient au moins une méthode
m
qui est pure virtual , c'est à dire déclarée
comme:
virtual m =0;
Toutefois, il y a des situations dans lesquelles on n'a aucun intérêt à utiliser ce type de bricolage, en raison de l'absence de sens de la super-classe abstraite. C'est par exemple le cas des objets pouvant répondre aux messages copy et paste, qui copient dans ou depuis le tampon la sélection courante, cela pouvant être du texte, un objet graphique, un font, ou , en général, n'importe quel objet sur lequel ces opérations ont un sens, et il risque d'y en avoir beaucoup. Utiliser l'approche de la classe abstraite oblige souvent, en plus, à implémenter l'héritage multiple. C'est pour cela qu'on retrouve dans les langages plus récents des mécanismes plus propres pour capturer la notion de ``conformance'' à un protocole de communication, c'est le cas des protocols dans Objective-C, repris pratiquement inchangés dans Java.
- classes abstraites/virtuelles
- sont fournies explicitement
en C++ et Java, et admises en Objective-C, mais sans support
syntactique spécifique
Voici un exemple en Java:
abstract class GraphicObject extend Object { abstract void affiche(); }
Voici un exemple en C++:class Rectangle extends GraphicObject { . . . // instance variables etc. void affiche() { // routine d'affichage }; }
virtual class GraphicObject { public: virtual void affiche(); }
class Rectangle : public GraphicObject { . . . // instance variables etc. void affiche() { // routine d'affichage } }
- protocoles
- sont fournis en Objective-C, et repris tel quels dans Java, où ils sont
appelés interfaces.
Voici un exemple en Objective-C:@protocol Affichable - (void) affiche; @end
Il faut noter que, comme le typage de Objective-C n'est pas sûr, on pourrait tout simplément utiliser une liste sans se soucier de la@interface AffichableList : List - addObject:(id<Affichable>)anObject; - affiche; @end
@implementation AffichableList - addObject:(id<Affichable>)anObject { [super addObject: anObject];}; - affiche { [self makeObjectsPerform: @selector(affiche)];}; @end
conformance'' de ses éléments, et c'est cela la pratique en <TT>Objective-C</TT>, mais les protocoles permettent d'introduire un peu de sûreté dans le typage. <P> Les protocoles deviennent cependant nécessaires lorsque on travaille avec des objets distribués.<BR> <P> En <TT>Java</TT>, un exemple typique d'interface est l'interface <A NAME="tex2html5" HREF="http://java.sun.com/java.sun.com/JDK-1.0/api/java.lang.Runnable.html"><TT>Runnable</TT></A>, qui déclare les méthodes nécessaires pour qu'un objet puissse être exécuté dans un thread.<BR> <P> Leur présence dans <TT>Java</TT> est nécessaire, en raison de la limitation à l'héritage simple qui empêche d'utiliser le mécanisme des classes abstraites trop à la légère (notamment, un heritage artificiel utilisé pour faire des classes abstraites peut gêner un vrai heritage). <P> </DL> <P> Ce problème est en général assez complexe, parce-que il a souvent à voir avec la nécessité de distinguer clairement entre la relation d'héritage, la relation de sous-typage et une forme plus faible de celle-ci que c'est la relation de
conformance'' vue en 1.2.
Next: La nécessité du polymorphisme Up: Héritage et polymorphisme vertical Previous: Classes dont on aurait Roberto DiCosmo
Mon Jun 3 18:29:31 MET DST 1996