Eu 'descobri' interfaces e comecei a amá-las. A beleza de uma interface é que ela é um contrato, e qualquer objeto que cumpra esse contrato pode ser usado sempre que a interface for necessária.
O problema com uma interface é que ela não pode ter uma implementação padrão, o que é um problema para propriedades comuns e derrota o DRY. Isso também é bom, porque mantém a implementação e o sistema dissociados. A herança, por outro lado, mantém um acoplamento mais rígido e tem o potencial de quebrar o encapsulamento.
Caso 1 (herança com membros privados, bom encapsulamento, fortemente acoplado)
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();
)
Caso 2 (apenas uma interface)
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.
Caso 3: (melhor dos dois mundos?)
Semelhante ao Caso 1 . No entanto, imagine que (hipoteticamente) o C ++ não permitisse métodos de substituição, exceto aqueles que são puramente virtuais .
Portanto, no Caso 1 , substituir do_work () causaria um erro em tempo de compilação. Para corrigir isso, configuramos do_work () como virtual puro e adicionamos um método separado increment_money_earned (). Como um exemplo:
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(); ); .
};
Mas mesmo isso tem problemas. E se daqui a três meses, Joe Coder criar um Médico Funcionário, mas ele esquecer de chamar increment_money_earned () em do_work ()?
A questão:
O caso 3 é superior ao caso 1 ? É por causa de 'melhor encapsulamento' ou 'mais frouxamente acoplado', ou algum outro motivo?
O Caso 3 é superior ao Caso 2 porque está em conformidade com o DRY?