Я «открыл» интерфейсы и начал любить их. Прелесть интерфейса в том, что это контракт, и любой объект, который выполняет этот контракт, может использоваться везде, где требуется этот интерфейс.
Проблема с интерфейсом состоит в том, что у него не может быть реализации по умолчанию, что является проблемой для мирских свойств и побеждает DRY. Это также хорошо, потому что это держит реализацию и систему разъединенной. Наследование, с другой стороны, поддерживает более плотную связь и может нарушить инкапсуляцию.
Случай 1 (Наследование с частными членами, хорошая инкапсуляция, тесно связанная)
class Employee
{
int money_earned;
string name;
public:
void do_work(){money_earned++;};
string get_name(return name;);
};
class Nurse : public Employee:
{
public:
void do_work(/*do work. Oops, can't update money_earned. Unaware I have to call superclass' do_work()*/);
};
void HireNurse(Nurse *n)
{
nurse->do_work();
)
Случай 2 (просто интерфейс)
class IEmployee
{
virtual void do_work()=0;
virtual string get_name()=0;
};
//class Nurse implements IEmployee.
//But now, for each employee, must repeat the get_name() implementation,
//and add a name member string, which breaks DRY.
Случай 3: (лучший из обоих миров?)
Аналогично случаю 1 . Однако представьте, что (гипотетически) C ++ не допускает переопределения методов, кроме тех, которые являются чисто виртуальными .
Итак, в случае 1 переопределение do_work () может вызвать ошибку во время компиляции. Чтобы это исправить, мы устанавливаем do_work () как чисто виртуальный и добавляем отдельный метод increment_money_earned (). Например:
class Employee
{
int money_earned;
string name;
public:
virtual void do_work()=0;
void increment_money_earned(money_earned++;);
string get_name(return name;);
};
class Nurse : public Employee:
{
public:
void do_work(/*do work*/ increment_money_earned(); ); .
};
Но даже у этого есть проблемы. Что если через 3 месяца Джо Кодер создаст сотрудника-доктора, но он забудет вызвать increment_money_earned () в do_work ()?
Вопрос:
Является ли случай 3 выше случай 1 ? Это из-за «лучшей инкапсуляции» или «более слабой связи», или по какой-то другой причине?
Является ли случай 3 превосходит случай 2 , поскольку он соответствует DRY?