Могут ли лямбды заменить геттеры? - PullRequest
1 голос
/ 10 декабря 2011

Вот классический пример класса с двумя геттерами для его полей:

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, но теперь, когда у нас есть лямбды, это кажется мне выполнимым.Является ли этот подход более обоснованным, чем первая версия с геттерами, или я слишком увлечен?

Как вы думаете?Насколько широко это применимо?Я что-то упускаю?Можно ли это улучшить?

Ответы [ 2 ]

4 голосов
/ 10 декабря 2011

Это было бы слишком неуклюже в C ++ 98

На самом деле, это довольно просто (по крайней мере, в c ++ 03):

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_);
    }
};

void foo(int,int)
{
}

int main()
{
    point p(3, 4);
    p(&foo);
}

Можно ли это улучшить?

Да: удалить геттеры и поместить x и y в публичный раздел:

struct point
{
  int x;
  int y
};
3 голосов
/ 10 декабря 2011
p([](int x, int y){
    std::cout << x << ", " << y << '\n';
});

IMO, необходимость писать лямбда-код вокруг некоторого кода вместо того, чтобы просто писать код, по-прежнему наглядна.

Единственное различие между наличием отдельных средств доступа и тем, что класс может предполагать, чтозначения всегда доступны вместе.Это просто может обеспечить новые способы получения тех значений, которые были бы невозможны, если бы каждый из них должен был создаваться индивидуально (например, возможно, намного дешевле запрашивать 2 значения за раз, чем делать 2 запроса для одного значения).

Последнее вряд ли имеет место для многих классов (например, Point), где нет реальной выгоды за счет более сложного использования.

...