Todavía estoy a años de comprender completamente la distinción entre una clase abstracta y una interfaz. Cada vez que creo tener una idea de los conceptos básicos, busco en stackexchange y estoy dos pasos atrás. Pero algunas reflexiones sobre el tema y la pregunta de los OP:
Primero:
Hay dos explicaciones comunes de una interfaz:
Una interfaz es una lista de métodos y propiedades que cualquier clase puede implementar, y al implementar una interfaz, una clase garantiza que esos métodos (y sus firmas) y esas propiedades (y sus tipos) estarán disponibles al "interactuar" con esa clase o Un objeto de esa clase. Una interfaz es un contrato.
Las interfaces son clases abstractas que no pueden / no pueden hacer nada. Son útiles porque puede implementar más de una, a diferencia de las clases principales para padres. Al igual, podría ser un objeto de la clase BananaBread y heredar de BaseBread, pero eso no significa que no pueda implementar las interfaces IWithNuts e ITastesYummy. Incluso podría implementar la interfaz IDoesTheDishes, porque no soy solo pan, ¿sabes?
Hay dos explicaciones comunes de una clase abstracta:
Una clase abstracta es, ya sabes, lo que no puede hacer. Es como, la esencia, en realidad no es algo real. Espera, esto te ayudará. Un barco es una clase abstracta, pero un sexy Playboy Yacht sería una subclase de BaseBoat.
Leí un libro sobre clases abstractas, y tal vez deberías leer ese libro, porque probablemente no lo entiendas y lo harás mal si no lo has leído.
Por cierto, el libro Citers siempre parece impresionante, incluso si todavía me alejo confundido.
Segundo:
En SO, alguien hizo una versión más simple de esta pregunta, el clásico, "¿por qué usar interfaces? ¿Cuál es la diferencia? ¿Qué me estoy perdiendo?" Y una respuesta usó un piloto de la fuerza aérea como un ejemplo simple. No aterrizó del todo, pero generó algunos comentarios excelentes, uno de los cuales mencionaba que la interfaz IFlyable tenía métodos como takeOff, pilotEject, etc. Y esto realmente me pareció un ejemplo real de por qué las interfaces no son solo útiles, pero crucial Una interfaz hace que un objeto / clase sea intuitivo, o al menos da la sensación de que lo es. Una interfaz no es para el beneficio del objeto o los datos, sino para algo que necesita interactuar con ese objeto. El clásico Fruit-> Apple-> Fuji or Shape-> Triangle-> Los ejemplos equiláteros de herencia son un gran modelo para comprender taxonómicamente un objeto dado en función de sus descendientes. Informa al consumidor y a los procesadores sobre sus cualidades generales, comportamientos, si el objeto es un grupo de cosas, controlará su sistema si lo coloca en el lugar equivocado, o describe datos sensoriales, un conector a un almacén de datos específico, o datos financieros necesarios para hacer la nómina.
Un objeto Plane específico puede o no tener un método para un aterrizaje de emergencia, pero me enojaré si asumo su emergencia y me gusta como cualquier otro objeto volador solo para despertar cubierto en DumbPlane y aprender que los desarrolladores fueron con quickLand porque pensaron que todo era lo mismo. Al igual que me sentiría frustrado si cada fabricante de tornillos tuviese su propia interpretación de righty tighty o si mi televisor no tuviera el botón de aumento de volumen por encima del botón de disminución de volumen.
Las clases abstractas son el modelo que establece lo que cualquier objeto descendiente debe tener para calificar como esa clase. Si no tienes todas las cualidades de un pato, no importa que tengas implementada la interfaz IQuack, eres un pingüino extraño. Las interfaces son las cosas que tienen sentido incluso cuando no puedes estar seguro de otra cosa. Jeff Goldblum y Starbuck pudieron volar naves espaciales alienígenas porque la interfaz era confiablemente similar.
Tercero:
Estoy de acuerdo con tu compañero de trabajo, porque a veces necesitas aplicar ciertos métodos desde el principio. Si está creando un ORM de registro activo, necesita un método de guardar. Esto no depende de la subclase que se puede instanciar. Y si la interfaz ICRUD es lo suficientemente portátil como para no estar exclusivamente acoplada a una clase abstracta, otras clases pueden implementarla para que sean confiables e intuitivos para cualquiera que ya esté familiarizado con cualquiera de las clases descendientes de esa clase abstracta.
Por otro lado, hubo un gran ejemplo anterior de cuándo no saltar para vincular una interfaz a la clase abstracta, porque no todos los tipos de lista implementarán (o deberían) una interfaz de cola. Dijiste que este escenario ocurre la mitad del tiempo, lo que significa que tú y tu compañero de trabajo están equivocados la mitad del tiempo y, por lo tanto, lo mejor que puedes hacer es discutir, debatir, considerar y, si resultan ser correctos, reconocer y aceptar el acoplamiento. . Pero no se convierta en un desarrollador que siga una filosofía incluso cuando no sea la mejor para el trabajo en cuestión.