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

Un livre de Wikilivres.
Contenu supprimé Contenu ajouté
Création
 
+
Ligne 1 : Ligne 1 :
<noinclude>{{NavTitre|book={{BASEPAGENAME}}|prev=Fantôme|next=Post-Redirect-Get}}{{Patrons de conception}}
<noinclude>{{NavTitre|book={{BASEPAGENAME}}|prev=Fantôme|next=Post-Redirect-Get}}{{Patrons de conception}}
{{Patron de conception|Double-dispatch|Double-dispatch|Permettre l'appel à une méthode surchargée en recourant au type dynamique d'un argument|[[../Autres patrons|Autre]]}}</noinclude>
{{Patron de conception|Double-dispatch|Double-dispatch|Permettre l'appel à une méthode surchargée en recourant au type dynamique d'un argument|[[../Autres patrons|Autre]]}}</noinclude>

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


== Introduction ==
== Introduction ==


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).
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 :
<source lang="java">
// Une classe Object comportant un attribut : le nom de l'objet
static 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
</source>
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 :
<source lang="java">
// 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)
</source>
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 <source lang="java">SimpleDisplay.display(SimpleObject, SimpleObject)</source> 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)


== Voir aussi ==
== Voir aussi ==

Version du 11 août 2011 à 19: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

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
static 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)

Voir aussi