Вот классический пример класса с двумя геттерами для его полей:
class point
{
int x_, y_;
public:
point(int x, int y) : x_(x), y_(y) {}
int x() const
{
return x_;
}
int y() const
{
return y_;
}
};
int main()
{
point p(1, 2);
std::cout << p.x() << ", " << p.y() << '\n';
}
Можно утверждать, что печать точки в выходной поток действительно должна обеспечиваться перегрузкой operator<<
,но давайте предположим, что клиент хочет напечатать в своем любимом формате или сделать что-то совершенно другое с помощью x и y.Тогда ему явно нужно как-то добраться до полей x и y, верно?
Основной принцип объектно-ориентированного программирования - «говори, не спрашивай».То есть в идеале я должен сказать своему объекту что-то делать с полями x и y, а не запрашивать их.Это привело меня к следующей идее:
class point
{
int x_, y_;
public:
point(int x, int y) : x_(x), y_(y) {}
template<typename Fun>
void operator()(Fun fun) const
{
fun(x_, y_);
}
};
int main()
{
point p(3, 4);
p([](int x, int y){
std::cout << x << ", " << y << '\n';
});
}
Это было бы слишком неуклюже в C ++ 98, но теперь, когда у нас есть лямбды, это кажется мне выполнимым.Является ли этот подход более обоснованным, чем первая версия с геттерами, или я слишком увлечен?
Как вы думаете?Насколько широко это применимо?Я что-то упускаю?Можно ли это улучшить?