D permet de surcharger des opérateurs comme +
, -
ou l'opérateur d'appel ()
pour les classes et les structures. Nous allons nous intéresser à la surcharge des opérateurs opDispatch
et opApply
.
opDispatch
peut être défini comme une méthode d'une struct
ou d'une class
. Chaque appel à une méthode indéfinie dans cet objet sera passé à opDispatch
en passant le nom de la méthode appelée en paramètre de modèle. opDispatch
est une méthode attrape-tout qui permet un autre niveau de programmation générique — et le tout à la compilation!
struct C
{
void callA(int i, int j) { //... }
void callB(string s) { //... }
}
struct CallLogger(C)
{
C content;
void opDispatch(string name, T...)(T vals)
{
writeln("called ", name);
mixin("content." ~ name)(vals);
}
}
CallLogger!C l;
l.callA(1, 2); // "called content.callA"
l.callB("ABC"); // "called content.callB"
Au lieu de définir une range, on peut implémenter la méthode opApply
pour appeler foreach
sur un objet personnalisé. Itérer sur ce genre de type appellera opApply
avec un delegate spécial en paramètre:
class Tree
{
Tree gauche;
Tree droite;
int opApply(int delegate(Tree) dg)
{
if(gauche && gauche.opApply(dg)) return 1;
if(dg(this)) return 1;
if(droite && droite.opApply(dg)) return 1;
return 0;
}
Tree tree = new Tree;
foreach(node; tree)
{
//...
}
}
Le compilateur transforme le corps du foreach
en un delegate() qui est passé à l'objet. Son unique paramètre contiendra le contenu courant de la valeur de l'itération. La valeur de retour int
doit être vérifiée et si ce n'est pas 0
, l'itération doit être arrêtée.