Soy consciente de que esta es una pregunta muy básica, pero un entrevistador me preguntó de una manera muy engañosa y yo estaba indefenso :(
Solo conozco la definición material o teórica de una interfaz y también la implementé en muchos proyectos en los que trabajé. Pero realmente no entiendo por qué y cómo es útil.
Tampoco entiendo una cosa en la interfaz. es decir, por ejemplo, usamos
conn.Dispose();
en bloque finalmente. Pero no veo que la clase esté implementando o heredando la IDisposable
interfaz (SqlConnection
clase ), quiero decir. Me pregunto cómo puedo simplemente llamar al nombre del método. También en lo mismo, no entiendo cómo funciona el método Dispose porque necesitamos implementar el cuerpo de la función con nuestra propia implementación para todos los métodos de interfaz. Entonces, ¿cómo se aceptan o nombran las interfaces como contratos? Estas preguntas siguieron rodando en mi mente hasta ahora y, francamente, nunca vi un buen hilo que explicara mis preguntas de una manera que pueda entender.
MSDN, como de costumbre, parece muy aterrador y no hay una sola línea clara allí ( Amigos, disculpen amablemente que están en el desarrollo de alto nivel, creo firmemente que cualquier código o artículo debería llegar a la mente de cualquiera que lo vea, por lo tanto, como muchos otros dicen, MSDN no es de uso ).
El entrevistador dijo:
Tiene 5 métodos y está feliz de implementarlo en la clase directamente, pero si tienes que elegir la clase o interfaz abstracta, ¿cuál eliges y por qué? Le respondí todas las cosas que leí en varios blogs diciendo ventajas y desventajas tanto de la clase abstracta como de la interfaz, pero él no está convencido, está tratando de entender "Por qué la interfaz" en general. "Por qué la clase abstracta" en general, incluso si puedo implementar los mismos métodos solo una vez y no voy a cambiarlo.
No veo ningún lugar en la red, podría conseguir un artículo que me explicara claramente sobre las interfaces y su funcionamiento. Soy uno de esos muchos programadores, que todavía no sé de interfaces (sé teóricos y métodos que utilicé) pero no estoy satisfecho de haberlo entendido con claridad.
SqlConnection
hereda loSystem.ComponentModel.Component
que implementaIDisposable
.SqlConnection
implementaIDisposable
.Respuestas:
Las interfaces son excelentes cuando quieres crear algo como esto:
En mi ejemplo, yo podría ser un desarrollador que escribe
MyLogClass
, y los otros desarrolladores podrían crear sus clases y, cuando quisieran iniciar sesión, implementaron la interfazIMyLogInterface
. Es como si me preguntaran qué necesitan implementar para usar elWriteLog()
métodoMyLogClass
. La respuesta la encontrarán en la interfaz.fuente
MyClass
yMyOtherClass
por qué no llamaría simplementeaClass.WriteLog()
por qué agregar ese paso adicional. La implementación deWriteLog()
seguiría siendo diferente para cada una de las clases, pero ya tiene el objeto, entonces, ¿por qué pasarlo a una clase de controlador?MyLogClass
WriteLog
método. Entonces su método puede manejar cualquier objeto que implementeIMyLogInterface
. Aquí hay otra publicación interesante.Una de las razones por las que uso interfaces es porque aumenta la flexibilidad del código. Digamos que tenemos un método que toma un objeto del tipo de clase Cuenta como parámetro, como por ejemplo:
El problema con esto es que el parámetro del método está fijo hacia la implementación de una cuenta. Esto está bien si nunca necesita ningún otro tipo de cuenta. Tome este ejemplo, que en su lugar utiliza una interfaz de cuenta como parámetro.
Esta solución no está fijada hacia una implementación, lo que significa que puedo pasarle una SuperSavingsAccount o una ExclusiveAccount (ambas implementando la interfaz IAccount) y obtener un comportamiento diferente para cada cuenta implementada.
fuente
Las interfaces son contratos que los implementadores deben seguir. Las clases abstractas permiten contratos más implementaciones compartidas, algo que las interfaces no pueden tener. Las clases pueden implementar y heredar múltiples interfaces. Las clases solo pueden extender una única clase abstracta.
Por qué Interface
IDbCommand
tieneSqlCommand
yOracleCommand
que implementan la interfaz de formas específicas )Por qué abstracto
fuente
DataContracts
) en un ensamblado .NET ( por ejemplo, Contracts.Shared.dll ) para que los consumidores de clientes .NET puedan interoperarChannelFactory
fácilmente usando ( evitando generar código a través de Agregar referencia de servicio, etc. ) o usando Agregar referencia de servicio con tipos compartidosEntonces, en este ejemplo, PowerSocket no sabe nada más sobre los otros objetos. Todos los objetos dependen de la energía proporcionada por PowerSocket, por lo que implementan IPowerPlug y, al hacerlo, pueden conectarse a él.
Las interfaces son útiles porque proporcionan contratos que los objetos pueden usar para trabajar juntos sin necesidad de saber nada más entre sí.
fuente
En una palabra, ¡debido al polimorfismo !
Si "Programa en una interfaz, no en una implementación", puede inyectar diferentes objetos que comparten la misma interfaz (tipo) en el método como argumento. De esta manera, el código de su método no se combina con ninguna implementación de otra clase, lo que significa que siempre está abierto para trabajar con objetos recién creados de la misma interfaz. (Principio de apertura / cierre)
fuente
C # no tiene escritura pato: solo porque sepa que un determinado método se implementa en un conjunto de clases concretas no significa que pueda tratarlas de todos modos con respecto a la llamada a ese método. La implementación de una interfaz le permite tratar todas las clases que la implementan como el mismo tipo de cosa, con respecto a lo que define esa interfaz.
fuente
Creo que ya se derramó mucha sangre al hacer estas preguntas, y muchos intentan resolver estos problemas explicando términos robóticos que ningún ser humano normal puede entender.
Así que primero. para saber por qué la interfaz y por qué abstractas, debes saber para qué sirven. Personalmente aprendí estos dos al aplicar Factory Class. encuentras un buen tuturial en este enlace
Ahora profundicemos en el enlace que ya di.
Tiene una clase de vehículo que puede cambiar según los requisitos del usuario (como agregar camión , tanque , avión , etc.).
y
y ambos tienen un contrato IChoice que simplemente dice que mi clase debería tener el método de compra
Ahora, verá, esa interfaz solo aplica el método,
Buy()
pero deja que la clase heredada decida qué hacer cuando lo implemente. Esta es la limitación de Interface, usando puramente interface, podrías terminar repitiendo alguna tarea que podemos implementar automáticamente usando abstact. En nuestro ejemplo, digamos, comprar cada vehículo tiene un descuento.Ahora, usando Factory Class, puede lograr lo mismo, pero al usar abstract, deja que la clase base ejecute el
Buy()
método.fuente
Con una interfaz puede hacer lo siguiente:
1) Cree interfaces segregadas que ofrezcan diferentes cortes de su implementación, lo que permite una interfaz más cohesiva.
2) Permita múltiples métodos con el mismo nombre entre interfaces, porque bueno, no tiene una implementación conflictiva, solo una firma.
3) Puede versionar y separar su interfaz independientemente de su implementación, asegurando que se cumpla un contrato.
4) Su código puede depender de la abstracción en lugar de la concreción, lo que permite la inyección de dependencia inteligente, incluida la inyección de Mocks de prueba, etc.
Estoy seguro de que hay muchas más razones, estas son solo algunas.
Una clase abstracta le permite tener una base parcialmente concreta para trabajar, esto no es lo mismo que una interfaz pero tiene sus propias cualidades, como la capacidad de crear una implementación parcial usando el patrón del método de plantilla.
fuente
Como muestra real de la respuesta de @ user2211290:
Ambos de
Array
yList
tienen interfazIList
. A continuación tenemos unstring[]
y unList<string>
y los verificamos con un método usando IList :fuente
Solo puede heredar de una clase abstracta. Puede heredar de múltiples interfaces. Esto determina lo que uso para la mayoría de los casos.
La ventaja de la clase abstracta sería que puede tener una implementación base. Sin embargo, en el caso de IDisposable, una implementación predeterminada es inútil, ya que la clase base no sabe cómo limpiar adecuadamente las cosas. Por tanto, una interfaz sería más adecuada.
fuente
Tanto la clase abstracta como la interfaz son contratos.
La idea de un contrato es que especifiques algún comportamiento. Si dice que ha implementado, ha aceptado el contrato.
La elección de abstracto sobre interfaz es.
Cualquier descendiente no abstracto de la clase abstracta implementará el contrato.
versus
Cualquier clase que implemente la interfaz implementará el contrato.
Por lo tanto, usa abstracto cuando desea especificar algún comportamiento que todos los descendientes deben implementar y ahorrarse la definición de una interfaz separada, pero ahora todo lo que cumple con este contrato agregado de manera efectiva debe ser un descendiente.
fuente
Las interfaces son para hacer una abstracción (un arquetipo) de la abstracción (las clases) de la realidad (los objetos).
Las interfaces deben especificar los términos del contrato sin proporcionar la implementación proporcionada por las clases.
Las interfaces son especificaciones:
Las interfaces son artefactos de tiempo de diseño para especificar el comportamiento inmóvil del concepto, ya que es solo y estático.
Las clases son artefactos de tiempo de implementación para especificar la estructura móvil de la realidad a medida que interactúa y se mueve.
¿Qué es una interfaz?
Cuando observas a un gato puedes decir que es un animal que tiene cuatro patas, una cabeza, un tronco, una cola y pelo. Puedes ver que puede caminar, correr, comer y maullar. Y así.
Acaba de definir una interfaz con sus propiedades y sus operaciones. Como tal, no ha definido ningún modus operandi, sino solo características y capacidades sin saber cómo funcionan las cosas: ha definido habilidades y distinciones.
Como tal, todavía no es una clase, aunque en UML la llamamos clase en un diagrama de clases porque podemos definir miembros privados y protegidos para comenzar a tener una visión profunda del artefacto. No se confunda aquí porque en UML una interfaz es algo ligeramente diferente a una interfaz en C #: es como un punto de acceso parcial al átomo de abstracción. Como tal, dijimos que una clase puede implementar múltiples interfaces. Como tal, es lo mismo, pero no, porque las interfaces en C # se usan para abstraer la abstracción y para limitar esta abstracción como un punto de acceso. Son dos usos diferentes. Así, una clase en UML representa una interfaz de acoplamiento completo a una clase de programación, mientras que una interfaz UML representa una interfaz de desacoplamiento de una sección de una clase de programación. En efecto, el diagrama de clases en UML no se ocupa de la implementación y todos sus artefactos están al nivel de la interfaz de programación. Si bien asignamos clases UML a clases de programación, es una transposición de abstracción abstracta a abstracción concreta. Hay una sutileza que explica la dicotomía entre el campo del diseño y el campo de la programación. Entonces, una clase en UML es una clase de programación desde el punto de vista de una interfaz de programación considerando cosas internas ocultas.
Las interfaces también permiten simular herencia múltiple cuando no está disponible de una manera incómoda. Por ejemplo, la clase cat implementará la interfaz cat que se deriva de la interfaz animal. Esta clase de gato también implementará estas interfaces: caminar, correr, comer y hacer un sonido. Esto compensa la ausencia de herencia múltiple a nivel de clase, pero cada vez necesitas reimplementar todo y no puedes factorizar la realidad en el mejor de los casos como lo hace la realidad misma.
Para entender eso podemos referirnos a la codificación de objetos Pascal donde se define en una unidad la interfaz y las secciones de implementación. En la interfaz se definen los tipos y en la implementación se implementa el tipo:
Aquí, la sección de interfaz coincide con el diseño de la clase UML, mientras que los tipos de interfaces son, por lo tanto, otras cosas.
Entonces, en nuestro negocio tenemos una palabra, interfaz , para nombrar dos cosas distintas pero similares, y es una fuente de confusión.
También en C #, por ejemplo, las interfaces de programación permiten compensar la ausencia de polimorfismo genérico verdadero en tipos abiertos sin realmente tener éxito en el objetivo porque perdió la habilidad fuertemente tipada.
Después de todo, las interfaces son necesarias para permitir que los sistemas incompatibles se comuniquen sin preocuparse por la implementación y la gestión de los objetos en la memoria como se introdujo con el Modelo de Objetos Comunes (Distribuido).
¿Qué es una clase?
Después de definir una reducción de la realidad desde un punto de vista externo, puedes describirla desde una perspectiva interna: esta es la clase en la que defines el procesamiento de datos y la gestión de mensajes para permitir que la realidad que has encapsulado cobre vida e interactúe gracias a los objetos que utilizan instancias.
Entonces en UML realizas una inmersión fractal en las ruedas de la maquinaria y describes los estados, las interacciones y así sucesivamente para poder implementar la abstracción del fragmento de la realidad que quieres manejar.
Como tal, una clase abstracta es de alguna manera el equivalente de una interfaz desde el punto de vista del compilador.
Más información
Protocolo (programación orientada a objetos)
C #: interfaces
C # - Clases
fuente
Déjame contarte sobre las tostadoras voladoras.
Hay, por supuesto, muchas situaciones en las que puede construir un sistema de software que funcione sin declarar o implementar ninguna interfaz: cualquier diseño de software orientado a objetos se puede realizar utilizando nada más que clases.
Por otra parte, cualquier sistema de software también se puede implementar en lenguaje ensamblador o, mejor aún, en código máquina. La razón por la que usamos mecanismos de abstracción es porque tienden a facilitar las cosas. Las interfaces son un mecanismo de abstracción.
Entonces, da la casualidad de que hay ciertos diseños orientados a objetos no triviales que son mucho más fáciles de implementar si usa interfaces, que las interfaces prácticamente se vuelven necesarias en esos casos.
Estos diseños no triviales tienen que ver con la herencia múltiple, que, en su forma "verdadera", es cuando una clase hereda no solo de una clase base, sino de dos o más clases base. Esta forma verdadera no es posible en C #, pero antes de que aparecieran lenguajes como C # y Java, el lenguaje que gobernaba era C ++, que es totalmente compatible con la verdadera herencia múltiple. Desafortunadamente, la verdadera herencia múltiple resultó no ser una muy buena idea, porque complica enormemente el diseño del lenguaje, y también da lugar a varios problemas, por ejemplo el famoso "Problema del Diamante". (Ver "¿Cuál es el problema exacto con la herencia múltiple?" Respuesta de J Francis )
Entonces, si alguien quisiera construir una clase de "tostadora voladora", heredaría de alguna clase de "tostadora" existente y también de alguna clase "voladora" existente. El tipo de problema con el que probablemente se encontraran era que la fuente de alimentación de la clase tostadora probablemente sería un enchufe de pared, mientras que la fuente de alimentación de la clase de máquinas voladoras probablemente sería comida para palomas, y la nueva clase resultante podría ser de alguna manera tener ambos, o no estaría claro cuál tendría. (El problema del diamante).
Los creadores de lenguajes como C # y Java decidieron no permitir la verdadera herencia múltiple, con el fin de mantener el lenguaje simple y evitar trampas como el problema del diamante. Sin embargo, todavía es necesaria alguna forma de herencia múltiple (o al menos muy deseable), por lo que en estos lenguajes introdujeron interfaces como un medio para admitir una forma menor de herencia múltiple evitando los problemas y la complejidad de la verdadera herencia múltiple.
En esta forma menor de herencia múltiple, no se le permite tener una clase que herede de más de una clase base, pero al menos puede heredar de una o más interfaces. Entonces, si desea construir una tostadora voladora, no puede heredar tanto de alguna clase de tostadora existente como de alguna clase voladora existente, pero lo que puede hacer es heredar de una clase de tostadora existente y luego también exponer una interfaz de vuelo que usted mismo implementa. posiblemente utilizando cualquier medio que ya haya heredado de la tostadora.
Por lo tanto, a menos que alguna vez sienta la necesidad de crear una clase que agregue dos conjuntos de funcionalidad diferentes y no relacionados, no necesitará ninguna forma de herencia múltiple, por lo que no necesitará declarar o implementar ninguna interfaz.
fuente
Las interfaces permiten al diseñador de clases dejar muy claros los métodos disponibles para el usuario final. También son una parte integral del polimorfismo.
fuente
No publicaré la definición de una interfaz en una clase abstracta porque creo que conoces muy bien la teoría y supongo que conoces los principios SOLID, así que seamos prácticos.
Como sabe, las interfaces no pueden tener ningún código, por lo que las ventajas son bastante sencillas de entender.
si necesita inicializar la propiedad de su clase proporcionando un constructor o si desea proporcionar parte de la implementación, una clase abstracta sería una buena opción contra una interfaz que no le permitiría hacer eso.
Entonces, en general, debe preferir la clase abstracta a las interfaces cuando necesite proporcionar un constructor o cualquier código al cliente que heredará / extenderá su clase
fuente
La clase abstracta se crea para entidades relacionadas, donde las interfaces se pueden usar para entidades no relacionadas.
Por ejemplo, si tengo dos entidades que dicen Animal y Human, iré a Interface donde, como si tuviera que ir en detalle, digamos Tiger, lion y quiero relacionarme con Animal, entonces elegiré la clase Animal Abstract.
se verá como a continuación
fuente