Quando usar interfaces ou classes abstratas? Quando usar os dois?

Embora algumas diretrizes indiquem que você deve usar uma interface quando quiser definir um contrato para uma classe em que a herança não esteja clara (IDomesticated) e herança quando a classe é uma extensão de outra (Cat : Mammal, Snake : Reptile), há casos em que (na minha opinião) essas diretrizes entram em uma área cinza.

Por exemplo, digamos que minha implementação foiCat : Pet. Pet é uma classe abstrata. Isso deve ser expandido paraCat : Mammal, IDomesticated OndeMammal é uma classe abstrata eIDomesticated é uma interface? Ou estou em conflito com oBEIJO/YAGNI princípios básicos (embora eu não tenha certeza se haveráWolf classe no futuro, que não seria capaz de herdarPet)

Afastando-se do metafóricoCatareiaPets, digamos que eu tenha algumas classes que representam fontes de dados recebidos. Todos eles precisam implementar a mesma base de alguma forma. Eu poderia implementar algum código genérico em um resumoSource classe e herda dele. Eu também poderia apenas fazer umaISource interface (que se sente mais "certo" para mim) e re-implementar o código genérico em cada classe (o que é menos intuitivo). Finalmente, eu poderia "ter o bolo e comê-lo" fazendo a classe abstrata e a interface. O que é melhor?

Esses dois casos trazem pontos para usar apenas uma classe abstrata, apenas uma interface e usando uma classe abstrata e uma interface. Todas essas escolhas são válidas ou há "regras" para quando uma deve ser usada em detrimento de outra?

Gostaria de esclarecer que "usando tanto uma classe abstrata e uma interface", que inclui o caso quando eles representam essencialmente a mesma coisa (Source eISource ambos têm os mesmos membros), mas a classe adiciona funcionalidade genérica enquanto a interface especifica o contrato.

Também vale a pena notar que esta questão é principalmente para linguagens que não suportam herança múltipla (como .NET e Java).

questionAnswers(7)

yourAnswerToTheQuestion