Мова D дозволяє перевизначати такі оператори, як +
, -
або оператори
виклику ()
для класів та структур.
Ми трохи ближче познайомимось з двома спеціальними операторами
для перевантаження opDispatch
і opApply
.
opDispatch
може бути визначений як функція-член структури
чи класу
.
Будь-який виклик до невизначеної функції-члену до цього типу
передається до opDispatch
разом із ім'ям такої невідомої функції,
як параметр шаблону string
. opDispatch
є всеперехоплюючою функцією,
яка забезпечує ще один рівень загального програмування, який повністю
розраховується під час компіляції!
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);
l.callB("ABC");
Альтернативний спосіб реалізації циклу foreach
окрім визначеного
користувачем діапазону, є реалізація opApply
. Виконання ітерації
з foreach
для такого типу викликатиме перенавантажений оператор
opApply
зі спеціальним делегатом, як параметр:
class Tree {
Tree lhs;
Tree rhs;
int opApply(int delegate(Tree) dg) {
if (lhs && lhs.opApply(dg)) return 1;
if (dg(this)) return 1;
if (rhs && rhs.opApply(dg)) return 1;
return 0;
}
}
Tree tree = new Tree;
foreach(node; tree) {
...
}
Компілятор трансформує тіло foreach
у спеціального делегата, який
передаватиметься об'єкту. Його один і єдиний параметр міститиме поточне
значення ітерації. Магічне повернення значення int
повинно бути
інтерпретовано і якщо воно не дорівнює 0
, ітерацію потрібно зупинити.