next up previous contents index
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();
}

class Rectangle extends GraphicObject { . . . // instance variables etc. void affiche() { // routine d'affichage }; }

Voici un exemple en C++:
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

@interface AffichableList : List - addObject:(id<Affichable>)anObject; - affiche; @end

@implementation AffichableList - addObject:(id<Affichable>)anObject { [super addObject: anObject];}; - affiche { [self makeObjectsPerform: @selector(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 conformance'' de ses &#233;l&#233;ments, et c'est cela la pratique en <TT>Objective-C</TT>, mais les protocoles permettent d'introduire un peu de s&#251;ret&#233; dans le typage. <P> Les protocoles deviennent cependant n&#233;cessaires lorsque on travaille avec des objets distribu&#233;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&#233;clare les m&#233;thodes n&#233;cessaires pour qu'un objet puissse &#234;tre ex&#233;cut&#233; dans un thread.<BR> <P> Leur pr&#233;sence dans <TT>Java</TT> est n&#233;cessaire, en raison de la limitation &#224; l'h&#233;ritage simple qui emp&#234;che d'utiliser le m&#233;canisme des classes abstraites trop &#224; la l&#233;g&#232;re (notamment, un heritage artificiel utilis&#233; pour faire des classes abstraites peut g&#234;ner un vrai heritage). <P> </DL> <P> Ce probl&#232;me est en g&#233;n&#233;ral assez complexe, parce-que il a souvent &#224; voir avec la n&#233;cessit&#233; de distinguer clairement entre la relation d'h&#233;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 up previous contents index
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