« Patrons de conception/Double-dispatch » : différence entre les versions

Un livre de Wikilivres.
Contenu supprimé Contenu ajouté
Ligne 145 : Ligne 145 :
== Voir aussi ==
== Voir aussi ==
* Ce patron de conception est une forme spécifique du patron [[../Visiteur/]].
* Ce patron de conception est une forme spécifique du patron [[../Visiteur/]].
* {{w|Double-dispatch}}
* {{en}} [[:en:w:Double-dispatch|Double-dispatch]]

Version du 15 août 2011 à 15:09

Patron de conception
Catégorie : Autre
Nom français : Double-dispatch
Nom anglais : Double-dispatch
Permettre l'appel à une méthode surchargée en recourant au type dynamique d'un argument


Ce patron de conception est lié à la notion de surcharge de méthode, et au polymorphisme. Il utilise le patron de conception Visiteur.

Introduction : notion de dispatch

Une classe peut définir une méthode qui peut être redéfinie dans une sous-classe (en C++ il s'agit de méthodes virtuelles, en Java toutes les méthodes sont virtuelles). La méthode réellement appelée est celle correspondant au type dynamique de l'objet (résolution à l'exécution, via une table de méthodes (vtable) par exemple), même si une référence à la classe de base est utilisée.

Exemple en Java :

// Une classe Object comportant un attribut : le nom de l'objet
class Object
{
	protected String name;
	public Object(String name)
	{ this.name = name; }
	public String toString()
	{ return "a "+name; }
}

// Une classe SimpleObject précisant que l'objet est simple
class SimpleObject extends Object
{
	public SimpleObject(String name)
	{ super(name); }
	public String toString()
	{ return "a simple "+name; }
}

// Le test :
Object book = new SimpleObject("book");
// référence de type Object mais objet de type SimpleObject
System.out.println(book.toString()); // SimpleObject.toString

Affiche :

a simple book

La plupart des langages de programmation orientés objet (C++, Java) se limite à cela concernant la résolution dynamique de types (donc à l'exécution plutôt qu'à la compilation). Ils ne permettent pas, par exemple, d'utiliser le type dynamique pour les arguments et déterminer quelle méthode surchargée appeler. Ces langages implémentent donc le simple-dispatch (un seul type résolu dynamiquement, celui de l'objet de l'appel à la méthode).

D'autres langages de programmation orientés objet permettent la résolution de type dynamique des arguments et la méthode surchargée appelée dépend du type réel et non du type de référence passé en argument. Cette fonctionnalité est appelée multiple-dispatch.

Exemple en Java où il n'existe que le simple-dispatch :

// NB: Les classes Object et SimpleObject de l'exemple précédent sont également
//     utilisées ici. Voir l'exemple précédent pour leur code source.

// Une classe Display pour afficher Object et SimpleObject
class Display
{
	public void display(Object o1, Object o2)
	{ System.out.println("A display for object ("+o1+") and object ("+o2+")"); }
	public void display(Object o1, SimpleObject o2)
	{ System.out.println("A display for object ("+o1+") and simple object ("+o2+")"); }
	public void display(SimpleObject o1, Object o2)
	{ System.out.println("A display for simple object ("+o1+") and object ("+o2+")"); }
	public void display(SimpleObject o1, SimpleObject o2)
	{ System.out.println("A display for simple object ("+o1+") and simple object ("+o2+")"); }
}

// Une classe SimpleDisplay pour afficher simplement Object et SimpleObject
class SimpleDisplay extends Display
{
	public void display(Object o1, Object o2)
	{ System.out.println("A simple display for object ("+o1+") and object ("+o2+")"); }
	public void display(Object o1, SimpleObject o2)
	{ System.out.println("A simple display for object ("+o1+") and simple object ("+o2+")"); }
	public void display(SimpleObject o1, Object o2)
	{ System.out.println("A simple display for simple object ("+o1+") and object ("+o2+")"); }
	public void display(SimpleObject o1, SimpleObject o2)
	{ System.out.println("A simple display for simple object ("+o1+") and simple object ("+o2+")"); }
}

// Le test :
Object book = new SimpleObject("book");
Object card = new SimpleObject("card");
Display disp = new SimpleDisplay();
disp.display(book, card); // -> SimpleDisplay.display(Object, Object)

Affiche :

A simple display for object (a simple book) and object (a simple card)

L'exemple précédent démontre que le langage Java ne permet pas nativement le multiple-dispatch. Dans le cas contraire, la méthode SimpleDisplay.display(SimpleObject, SimpleObject) aurait été appelée et l'affichage aurait été le suivant :

A simple display for simple object (a simple book) and simple object (a simple card)

Double-dispatch

Le double-dispatch est un patron de conception utilisant le patron Visiteur pour implémenter partiellement le multiple-dispatch, étendant le simple-dispatch en utilisant le type dynamique de l'un des arguments.

Le principe est d'ajouter une méthode dans les classes des arguments, appelée grâce au polymorphisme (le simple-dispatch). Cette méthode appelant la méthode originale, avec le pointeur this en argument dont le type réel est connu à la compilation.

Exemple en Java :

// Une classe Object comportant un attribut : le nom de l'objet
class Object
{
	protected String name;
	public Object(String name)
	{ this.name = name; }
	public String toString()
	{ return "a "+name; }
// méthode ajoutée pour implémentation du double-dispatch:
	public void display(Display d)
	{ d.display(this); } // this de type Object
}

// Une classe SimpleObject précisant que l'objet est simple
class SimpleObject extends Object
{
	public SimpleObject(String name)
	{ super(name); }
	public String toString()
	{ return "a simple "+name; }
// méthode ajoutée pour implémentation du double-dispatch:
	public void display(Display d)
	{ d.display(this); } // this de type SimpleObject
}

// Une classe Display pour afficher Object et SimpleObject
class Display
{
	public void display(Object o1)
	{ System.out.println("A display for object ("+o1+")"); }
	public void display(SimpleObject o1)
	{ System.out.println("A display for simple object ("+o1+")"); }
}

// Une classe SimpleDisplay pour afficher simplement Object et SimpleObject
class SimpleDisplay extends Display
{
	public void display(Object o1)
	{ System.out.println("A simple display for object ("+o1+")"); }
	public void display(SimpleObject o1)
	{ System.out.println("A simple display for simple object ("+o1+")"); }
}

// Le test :
Object book = new SimpleObject("book");
Display disp = new SimpleDisplay();
book.display(disp); // SimpleObject.display(Display) -> SimpleDisplay.display(SimpleObject)

Affiche :

A simple display for simple object (a simple book)

Voir aussi