D позволяет переопределять операторы, такие как
+
, -
или оператор вызова ()
для
классов и структур.
Взглянем поближе на переопределение специальных операторов
opDispatch
и opApply
.
opDispatch
можно определить как функцию-член для типов
struct
или class
. Все неизвестные вызовы членов такого типа
передаются в 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("вызов ", 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
,
прекратить цикл.