Лучший способ псевдоним методов члена объекта? "Сквозные методы" - PullRequest
0 голосов
/ 02 июня 2011

Рассмотрим следующий код:

class Rectangle
{
public:
    // Constructors
    Rectangle(){ init(0,0); }
    Rectangle(int h, int w){ init(h,w); }

    // Methods
    void init(int h, int w)
    {
        _h = h;
        _w = w;
    }

    // Getters / Setters
    double get_h(void){ return _h; }
    double get_w(void){ return _w; }
    void set_h(double h){ _h = h;  }
    void set_w(double w){ _w = w;  }
    std::string get_name(void){ return _name; }
    void set_name(std::string name){ _name = name; }

private:
    // Private Members
    int _h, _w;
    std::string _name;
};

class House
{
public: 
    // <BEGIN PASSTHROUGHS>
    std::string get_b_name(void){ return _base.get_name() };
    std::string get_r_name(void){ return _roof.get_name() };
    void set_b_name(std::string name){ _base.set_name(name); }
    void set_r_name(std::string name){ _roof.set_name(name); }
    // </END PASSTHROUGHS>

private:
    // Private Members
    Rectangle _base;
    Triangle  _roof;
};

Этот код отлично работает.

Мой вопрос касается функций "passthrough" в классе House, заключенных в теги PASSTHROUGHS. Это лучший способ сделать это? Аргументы и возвращаемые типы всегда будут совпадать, и в этих сквозных функциях нет «интеллекта», кроме как сделать вещи чище и проще.

Мой инстинкт был бы что-то вроде одного из следующих:

get_b_name = _base.get_name;

// OR

std::string get_b_name(void) = _base.get_name;

... но, похоже, ни один из них не работает, к сожалению, и в первую очередь это было только желаемое за действительное. Если нет более простых вариантов, скажите мне, что это тоже хорошо. Спасибо!

Ответы [ 2 ]

4 голосов
/ 02 июня 2011

Проблема, я думаю, является концептуальной.Ваш дизайн совершенно не объектно-ориентирован в том смысле, что дом не представляет собой объект, а скорее обеспечивает немного клея вокруг компонентов.С этой точки зрения было бы более разумно предоставлять средства доступа к элементам, а не сквозные функции:

class House {
   Rectangle _base;
   Triangle  _roof;
public:
   const Rectangle& base() const {
      return _base;
   }
   const Triangle& roof() const {
      return _roof;
   }
};

Я полагаю, что это всего лишь игрушечный пример, но применимы те же соображения: классдолжен представлять объект, для которого предварительно сформирован набор операций, в некоторых случаях эти операции могут быть реализованы с точки зрения внутренних подобъектов, но они все еще являются операциями над типом, и способ их сбора является подробностью реализации.

Рассмотрим:

class House {
   Thermostat t;
public:
   int temperature() const {
      return t.temperature();
   }
};

С точки зрения пользователя, в доме есть температура, которая может быть считана, и в этой конкретной реализации она считывается с термостата, который является членом.Но это деталь реализации.Возможно, вы захотите позже установить больше термостатов в доме и заменить одно чтение средним значением, но это не изменит тот факт, что у объекта Дом (в этой модели) есть температура.

Товы должны думать не о реализации сквозных функций, а о реализации функций типа.Если реализация оказывается одной пересылкой во внутренний метод, это нормально.

Но если тип содержит внутренние элементы и имеет смысл обращаться к свойствам элементов, учтите, что, возможно, ваш тип должен просто предоставить доступ к его внутренним элементам.Предположим, что вы хотите переместить пианино в доме, тогда вы можете просто предоставить доступ к дверному проему и позволить пользователю проверить:

class House {
   Door d;
public:
   Door const & door() const {
      return d;
   }
};
bool can_enter_piano( House const & h, Piano const & p ) {
   return h.door().width() > p.size();
}

Нет необходимости предоставлять House::get_door_width() и House::get_door_color() чтобы вы могли описать вход другу, и House::get_door_handle(), чтобы они могли знать, когда они приедут ...

0 голосов
/ 02 июня 2011

Это возможно потому, что ваш дизайн противоречив.С какой стати вы делаете открытую переменную-член, а затем пишете функцию, которая просто пересылает функции одной из этих переменных?Как пользователь вашего класса, я бы сам вызвал функцию для публичной переменной.Вы просто путаете меня, предоставляя два способа сделать то же самое.Или написать геттеры и сеттеры для класса Rectangle?Эта вещь - просто набор переменных, и ей не нужны никакие методы получения и установки.Вы точно не собираетесь наследовать от него, и вы не можете реально изменить внутреннюю логику и поддерживать ту же семантику, поэтому очень бессмысленно не просто делать переменные общедоступными.

Класс Rectangle нуждается вочень здоровая доза YAGNI , и классу Хауса просто нужно снова взглянуть на себя.Тот факт, что в «сквозных» методах нет интеллекта, должен быть огромным сигналом тревоги, говорящим вам о том, что они, скорее всего, являются избыточными и бесполезными - тем более, что вы не можете изменять публичные переменные, не нарушая интерфейс в любом случае, это не похоже нагеттеры и сеттеры уменьшают связь или что-то в этом роде.

Методы должны выполнять логика , или, по крайней мере, существуют, когда логика может быть обязательной.

...