Наследование против агрегирования и «has-a» против «is-a».

В моем коде я считаю полезным использовать наследование, подобное миксину, для компоновки объектов с разными блоками. У меня есть:

class Name
{
public:
    typedef int32_t value_type;

public:
    // ctors and dtors
    void set_value(value_type value) { value_ = value; }
    const value_type& value() const { return value_; }

private:
    value_type value_;
};

class NamedObject
{
public:
    void set_name(const Name& name) { name_ = name; }
    const Name& name() const { return name_; }

protected:
    // ctors and dtors

private:
    Name name_;
};

И я использую этот вид базовых классов для предоставления объектам свойств с заранее определенной невиртуальной функциональностью:

class MyObject: public NamedObject, public HasZlevel {
  // functionality that is not connected with NamedObject and HasZLevel
};

Поэтому я решаю рассматривать MyObject как «is-a» NamedObject вместо «has-a» "Имя. Z-level и Name - это свойства, которые никогда не изменятся в течение жизни экземпляра MyObject. Я предпочитаю это агрегации из-за упрощенного использования в алгоритмах, которые определены только для NamedObjects, или для объектов, имеющих интерфейс HasZLevel, я могу передать их через NamedObject * или HasZLevel * и быть уверенным, что они не будут удалены или добавлены из-за защищенных dtors и ctors.

Другой вариант - агрегация:

class MyObject
{
public:
    MyObject(const Name& name): name_(name) {}
    void set_name(const Name& name) { named_->set_name(name) }

    // and so on...

private:
    Name name_;
};

Чтобы использовать это, мне нужен шаблонный алгоритм, который требует от типа параметра, чтобы он имел функцию-член set_name.

Есть ли в моем случае какие-либо веские причины отказаться от моего подобного миксину спроектировать и использовать агрегацию? Может быть, при долгосрочном обслуживании и модификации?

5
задан Riga 19 March 2013 в 19:20
поделиться