Навеяло темой Снова о статической типизации . Там всё как-то сложно, для умных, через мьютексы. Я решил упростить задачу для понимания обычными программистами:
Есть три функции, которые должны всегда идти по порядку. То есть func_1(), func_2(), func_3() - правильно, а func_3(), func_2(), func_1() или func_2(), func_1(), func_3() - неправильно. Ошибка должна определяться на этапе компиляции.
Решаем с помощью немного нестандартного чейнинга:
#include <iostream>
using namespace std;
class Chain3
{
private:
Chain3(){}
public:
friend class Chain2;
void func_3()
{
cout << "func_3()" << endl;
}
};
class Chain2
{
private:
Chain3 chain3{};
Chain2(){}
public:
friend class Chain1;
Chain3 & func_2()
{
cout << "func_2()" << endl;
return chain3;
}
};
class Chain1
{
private:
Chain2 chain2{};
public:
Chain2 & func_1()
{
cout << "func_1()" << endl;
return chain2;
}
};
int main()
{
Chain1().func_1().func_2().func_3();
return 0;
}
Так как в каждом звене кроме последнего возвращается ссылка на объект определённого класса, то можно сказать, что статическая типизация используется для задания порядка. Если у всех трёх функций будет одинаковые имена, то порядок всё равно будет жёсткий. При динамической типизации его не будет.
Кроме типизации тут использованы ещё и особенности языка C++, позволяющие обойтись без макросов. В си или расте, вероятно, без макросов не получится. На Go, вероятно, такой код вообще не написать, хотя там и статическая типизация.
Цепочку можно легко продлить. Можно сделать даже не цепочку, а дерево, но при этом листья будут идти за ветвями, ветви за стволом и т.д.