Recientemente, comencé a entender cómo funciona la OOP, y ahora llego al punto en que cuanto más leo sobre las diferencias entre las clases abstractas y las interfaces, más me confundo. Hasta ahora, ninguno puede ser instanciado. Las interfaces son planos más o menos estructurales que determinan que el esqueleto y los resúmenes son diferentes al poder implementar parcialmente el código.
Me gustaría aprender más sobre estos a través de mi situación específica. Aquí hay un enlace a mi primera pregunta si desea un poco más de información de fondo: ¿Cuál es un buen modelo de diseño para mi nueva clase?
Aquí hay dos clases que creé:
class Ad {
$title;
$description
$price;
function get_data($website){ }
function validate_price(){ }
}
class calendar_event {
$title;
$description
$start_date;
function get_data($website){ //guts }
function validate_dates(){ //guts }
}
Entonces, como puede ver, estas clases son casi idénticas. No se muestran aquí, pero hay otras funciones, like get_zip()
, save_to_database()
que son comunes en mis clases. También he agregado otras clases Cars y Pets que tienen todos los métodos comunes y, por supuesto, propiedades específicas de esas clases (kilometraje, peso, por ejemplo).
Ahora he violado el principio DRY y estoy administrando y cambiando el mismo código en varios archivos. Tengo la intención de tener más clases como botes, caballos o lo que sea.
Entonces, ¿es aquí donde usaría una interfaz o una clase abstracta? Por lo que entiendo sobre las clases abstractas, usaría una superclase como plantilla con todos los elementos comunes integrados en la clase abstracta, y luego agregaría solo los elementos específicamente necesarios en futuras clases. Por ejemplo:
abstract class content {
$title;
$description
function get_data($website){ }
function common_function2() { }
function common_function3() { }
}
class calendar_event extends content {
$start_date;
function validate_dates(){ }
}
¿O usaría una interfaz y, debido a que son tan similares, crearía una estructura que cada una de las subclases se ve obligada a usar por razones de integridad, y se la dejaría al desarrollador final que desarrolle esa clase para ser responsable de cada una de las subclases? detalles de incluso las funciones comunes. Creo que es posible que algunas funciones 'comunes' deban ajustarse en el futuro para las necesidades de su clase específica.
A pesar de todo lo anterior, si cree que estoy malinterpretando el qué y el por qué de las clases e interfaces abstractas, ¡deje que una respuesta válida deje de pensar en esta dirección y sugiera la forma correcta de avanzar!
¡Gracias!
fuente
Respuestas:
En términos simples:
Las interfaces son para el tipo de relaciones "puede hacer / pueden tratarse como" .
Las clases abstractas (así como concretas) son para "es un" tipo de relación.
Mira estos ejemplos:
Bird
,Mosquito
YHorse
sonAnimals
. Están relacionados. Heredan métodos comunes de Animal likeeat(), metabolize() and reproduce()
. Tal vez anulan estos métodos, agregando un poco más a ellos, pero aprovechan el comportamiento predeterminado implementado en Animal comometabolizeGlucose().
Plane
no está relacionado conBird
,Mosquito
oHorse
.Flight
se implementa mediante clases diferentes, no relacionadas, comoBird
yPlane
.AccountableAsset
también es implementado por clases diferentes, no relacionadas, comoPlane
yRaceHorse
.Horse
no implementa Flight.Como puede ver, las clases (abstractas o concretas) lo ayudan a construir una jerarquía , permitiéndole heredar código de los niveles superiores a los niveles inferiores de la jerarquía. En teoría, cuanto más bajo está en la jerarquía, más especializado es su comportamiento, pero no tiene que preocuparse por muchas cosas que ya se han solucionado.
Las interfaces , por otro lado, no crean jerarquía, pero pueden ayudar a homogeneizar ciertos comportamientos en las jerarquías para que pueda abstraerlos de la jerarquía en ciertos contextos.
Por ejemplo, puede hacer que un programa sume el valor de un grupo
AccountableAssets
independientemente de su serRaceHorses
oPlanes
.fuente
can do/can be treated as
dónde las clases abstractas actúan como fundamentales!Podrías deducir la respuesta lógicamente ya que pareces ser consciente de las diferencias entre los dos.
Las interfaces definen un contrato común. Tal como una interfaz llamada IAnimal, donde todos los animales comparten funciones como Eat (), Move (), Attack () etc. Mientras que todos comparten las mismas funciones, todos o la mayoría de ellos tienen una forma diferente (implementación) de lograr eso.
Las clases abstractas definen una implementación común y, opcionalmente, contratos comunes. Por ejemplo, una calculadora simple podría calificar como una clase abstracta que implementa todos los operadores lógicos y bit a bit básicos y luego se extiende mediante ScientificCalculator, GraphicalCalculator, etc.
Si tiene una implementación común, entonces, por todos los medios, encapsule la funcionalidad en una clase abstracta para ampliarla. Tengo cerca de 0 experiencia PHP, pero no creo que pueda crear interfaces con campos no constantes. Si los campos son comunes entre sus clases de instancia, entonces se ve obligado a usar una clase Abstract, a menos que defina el acceso a ellos a través de getters y setters.
Además, parece que no hay escasez de resultados en Google.
fuente
Larga historia corta. Las clases abstractas son muy parecidas a las interfaces, ya que ambas proporcionan una plantilla de los métodos que deberían estar dentro de la clase heredada, pero existen grandes diferencias: - Las interfaces solo definen nombres / tipos de métodos que deben existir en una clase heredada, mientras que los abs- las clases pueden tener un código de método predeterminado completo y solo los detalles deben ser anulados. - Las interfaces no pueden tener modificadores de acceso. - Las interfaces no pueden tener campos. - Las clases no pueden tener herencia múltiple de clases, mientras que pueden heredar múltiples interfaces. - Además, las clases proporcionan una estructura jerárquica para que solo las clases derivadas de una clase específica deban seguir las pautas de la clase abstracta: objeto-> objeto específico-> objeto muy específico. Las interfaces, por otro lado, pueden ser heredadas por cualquier persona en cualquier lugar.
En mi opinión, las clases abstractas son más comunes porque pueden proporcionar una implementación predeterminada de código de inmediato, pero en proyectos a gran escala en los que necesita estandarizar ciertas clases, las interfaces pueden ser útiles.
Espero que ayude, pero hay mucha información sobre esto en línea, Leo
fuente
Classes cannot have multiple inheritance
- Es cierto para lenguajes como Java y C #, no es cierto para C ++.En primer lugar, debe comprender que a menudo proporcionará tanto una interfaz como una clase abstracta. La razón de esto, y la diferencia principal entre los dos, es que le permiten reutilizar un código diferente y así resolver diferentes problemas.
Las interfaces le permiten reutilizar el código del cliente con diferentes implementaciones. Un cliente de su clase get_data ($ sitio web) no se preocupa por los elementos $ title o $ description. Solo quiere indicarle a su contenido que cargue los datos. Si tiene diferentes tipos de contenido, algunos de los cuales necesitan una descripción $ y otros no, puede proporcionar una clase ContentInterface que solo especifique la firma de sus clases secundarias. Ahora el cliente puede tener cualquier cantidad de Contenidos diferentes sin saber exactamente cómo funcionan. El principio de sustitución de liskov es una buena cosa para leer acerca de estudiar esta idea. También me gusta la escritura del tío Bob sobre el tema. Las interfaces son muy importantes para las pruebas unitarias, y crear interfaces es un buen hábito para aprender.
Las clases abstractas le permiten reutilizar detalles de implementación comunes en un conjunto de clases que comparten un antepasado común. En su pregunta, parece tener una buena idea de por qué heredaría la implementación de una clase abstracta. Todavía es peligroso depender de los elementos internos de una clase base: es muy fácil violar la encapsulación y crear niños que dependen de detalles de implementación específicos de una clase base. El patrón de método de plantilla proporciona un ejemplo común y saludable de cómo usar clases base sin violar la encapsulación.
Entonces, como espero haber mostrado, a menudo proporcionará interfaces para los clientes de su jerarquía de clases, de modo que pueda cambiar su implementación de manera segura sin afectar el código del cliente. Esto le permite al cliente escribir pruebas unitarias utilizando Objetos simulados que heredan su interfaz. Y también proporcionará clases abstractas que permiten la reutilización de la lógica común o imponen semántica para las clases secundarias.
fuente
La diferencia es sutil pero clara. La interfaz trata sobre el comportamiento polimórfico. La clase abstracta trata sobre la reutilización y el comportamiento polimórfico.
Si desea poner énfasis en la reutilización y el comportamiento polimórfico, elija la clase abstracta. Por ejemplo, los diferentes tipos de empleados tienen disposiciones diferentes, pero todos reciben algunos comunes. Entonces, la clase abstracta es adecuada para representarla porque los puntos en común se pueden expresar en una clase abstracta base
Employee
y la diferencia se puede implementar en clases derivadas comoManager
oWorker
etc.Si desea poner énfasis solo en el comportamiento polimórfico, elija la interfaz. La interfaz tiene más que ver con el contrato, es decir, un objeto o una jerarquía que dice que se ajusta a cierto comportamiento. Por ejemplo, todos los empleados tienen una provisión de licencia, pero diferentes tipos de empleados tienen diferentes tipos de provisiones. Por lo tanto, cada tipo diferente de empleado requiere una calculadora de licencia diferente. Aquí la interfaz es una buena opción porque todos los tipos de empleados pueden implementar una
LeaveCalculator
interfaz con unCalculate()
comportamiento diferente.fuente
fuente