„Odkryłem” interfejsy i zacząłem je kochać. Piękno interfejsu polega na tym, że jest to umowa, a każdy obiekt spełniający tę umowę może być używany wszędzie tam, gdzie wymagany jest interfejs.
Problem z interfejsem polega na tym, że nie może on mieć domyślnej implementacji, co utrudnia przyziemne właściwości i pokonuje DRY. Jest to również dobre, ponieważ utrzymuje implementację i system odłączony. Dziedziczenie, z drugiej strony, utrzymuje ściślejsze połączenie i może potencjalnie zerwać hermetyzację.
Przypadek 1 (Dziedziczenie z członkami prywatnymi, dobre enkapsulacja, ściśle powiązane)
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();
)
Przypadek 2 (tylko interfejs)
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.
Przypadek 3: (najlepszy z obu światów?)
Podobnie jak w przypadku 1 . Wyobraź sobie jednak, że (hipotetycznie) C ++ nie zezwalał na metody zastępujące, z wyjątkiem metod czysto wirtualnych .
Tak więc w przypadku 1 zastąpienie do_work () spowodowałoby błąd czasu kompilacji. Aby to naprawić, ustawiamy do_work () jako czystą wirtualną i dodajemy osobną metodę increment_money_earned (). Jako przykład:
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(); ); .
};
Ale nawet to ma problemy. Co jeśli za 3 miesiące Joe Coder utworzy Doktora, ale zapomni o wywołaniu increment_money_earned () w do_work ()?
Pytanie:
Czy przypadek 3 jest lepszy od przypadku 1 ? Czy to dlatego, że jest to „lepsza enkapsulacja” lub „luźniej sprzężona”, czy z innego powodu?
Czy przypadek 3 jest lepszy od przypadku 2, ponieważ jest zgodny z DRY?