Ainda estou a anos de compreender completamente a distinção entre uma classe abstrata e uma interface. Toda vez que acho que entendo os conceitos básicos, vou procurar no stackexchange e estou a dois passos para trás. Mas algumas reflexões sobre o tópico e os POs questionam:
Primeiro:
Existem duas explicações comuns para uma interface:
Uma interface é uma lista de métodos e propriedades que qualquer classe pode implementar e, ao implementar uma interface, uma classe garante que esses métodos (e suas assinaturas) e essas propriedades (e seus tipos) estarão disponíveis ao "interagir" com essa classe ou um objeto dessa classe. Uma interface é um contrato.
Interfaces são classes abstratas que não podem / não podem fazer nada. Eles são úteis porque você pode implementar mais de uma, diferentemente das classes pai médias. Tipo, eu poderia ser um objeto da classe BananaBread e herdar do BaseBread, mas isso não significa que também não posso implementar as interfaces IWithNuts e ITastesYummy. Eu poderia até implementar a interface IDoesTheDishes, porque não sou apenas pão, sabe?
Existem duas explicações comuns para uma classe abstrata:
Uma classe abstrata é, sabe, a coisa que não é o que ela pode fazer. É como, a essência, não é realmente uma coisa real. Espere, isso vai ajudar. Um barco é uma classe abstrata, mas um sexy Playboy Yacht seria uma subclasse do BaseBoat.
Li um livro sobre aulas abstratas, e talvez você deva ler esse livro, porque provavelmente não o entende e o fará errado se ainda não o leu.
A propósito, o livro Citers sempre parece impressionante, mesmo que eu ainda vá embora confusa.
Segundo:
No SO, alguém perguntou uma versão mais simples dessa pergunta, o clássico "por que usar interfaces? Qual é a diferença? O que estou perdendo?" E uma resposta usou um piloto da força aérea como um exemplo simples. Não deu certo, mas provocou ótimos comentários, um dos quais mencionou a interface IFlyable com métodos como takeOff, pilotEject etc. Isso realmente me chamou a atenção como um exemplo real do porquê as interfaces não são apenas úteis, mas crucial. Uma interface torna um objeto / classe intuitivo ou, pelo menos, dá a sensação de que é. Uma interface não é para o benefício do objeto ou dos dados, mas para algo que precisa interagir com esse objeto. O clássico Frutas-> Maçã-> Fuji ou Forma-> Triângulo-> Exemplos equivalentes de herança são um ótimo modelo para entender taxonomicamente um determinado objeto com base em seus descendentes. Informa o consumidor e os processadores sobre suas qualidades gerais, comportamentos, se o objeto é um grupo de coisas, mangueira seu sistema se você o colocar no lugar errado ou descreve dados sensoriais, um conector para um armazenamento de dados específico ou dados financeiros necessários para fazer a folha de pagamento.
Um objeto específico do avião pode ou não ter um método para um pouso de emergência, mas eu vou ficar chateado se eu assumir sua terra de emergência, como qualquer outro objeto passível de voar, apenas para acordar coberto no DumbPlane e descobrir que os desenvolvedores foram com o quickLand porque eles pensaram que era tudo a mesma coisa. Assim como eu ficaria frustrado se cada fabricante de parafusos tivesse sua própria interpretação de righty tighty ou se minha TV não tivesse o botão de aumento de volume acima do botão de diminuição de volume.
Classes abstratas são o modelo que estabelece o que qualquer objeto descendente deve ter para se qualificar como essa classe. Se você não possui todas as qualidades de um pato, não importa se a interface do IQuack foi implementada, você é apenas um pinguim estranho. Interfaces são as coisas que fazem sentido, mesmo quando você não pode ter certeza de mais nada. Jeff Goldblum e Starbuck foram capazes de voar naves alienígenas porque a interface era similarmente confiável.
Terceiro:
Eu concordo com o seu colega de trabalho, porque às vezes você precisa aplicar certos métodos desde o início. Se você estiver criando um ORM do Active Record, ele precisará de um método de salvamento. Isso não depende da subclasse que pode ser instanciada. E se a interface ICRUD for portátil o suficiente para não ser acoplada exclusivamente à classe abstrata abstrata, ela poderá ser implementada por outras classes para torná-las confiáveis e intuitivas para qualquer pessoa que já esteja familiarizada com qualquer uma das classes descendentes dessa classe abstrata.
Por outro lado, havia um ótimo exemplo anterior de quando não pular para vincular uma interface à classe abstrata, porque nem todos os tipos de lista implementam (ou deveriam) implementar uma interface de fila. Você disse que esse cenário acontece na metade do tempo, o que significa que você e seu colega de trabalho estão errados na metade do tempo e, portanto, a melhor coisa a fazer é discutir, debater, considerar e, se eles estiverem certos, reconhecer e aceitar o acoplamento . Mas não se torne um desenvolvedor que segue uma filosofia, mesmo quando não é a melhor para o trabalho em questão.