¿Por qué debería usar Interfaces en C # cuando puedo implementar los métodos directamente?

Soy consciente de que esta es una pregunta muy básica, pero un entrevistador me preguntó de una manera muy truculenta y me sentí impotente 🙁

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 esto ú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 IDisposable ( SqlConnection ), 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 continuaron en mi mente hasta ahora y, francamente, nunca vi ningún hilo bueno que explicara mis preguntas de una manera que yo pueda entender.

MSDN como de costumbre parece muy aterrador y no hay una sola línea clara allí ( Amigos, disculpen amablemente a los que están en desarrollo de alto nivel, creo firmemente que cualquier código o artículo debe 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 le complace implementarlo directamente en la clase, pero si tiene que ir a la clase o interfaz abstracta, ¿cuál elige 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 “Why Interface” en general. “Por qué clase abstracta” en general, incluso si puedo implementar los mismos métodos solo una vez y no cambiarlo.

No veo ningún lugar en la red, podría obtener un artículo que me explique claramente sobre las interfaces y su funcionamiento. Soy uno de esos muchos progtwigdores, que todavía no conocen las interfaces (conozco los métodos teóricos y prácticos que utilicé), pero no estoy satisfecho de haberlo entendido claramente.

Las interfaces son excelentes cuando quieres crear algo así:

  using System; namespace MyInterfaceExample { public interface IMyLogInterface { //I want to have a especific method that I'll use in MyLogClass void WriteLog(); } public class MyClass:IMyLogInterface { public void WriteLog() { Console.Write("MyClass was Logged"); } } public class MyOtherClass :IMyLogInterface { public void WriteLog() { Console.Write("MyOtherClass was Logged"); Console.Write("And I Logged it different, than MyClass"); } } public class MyLogClass { //I created a WriteLog method where I can pass as parameter any object that implement IMyLogInterface. public static void WriteLog(IMyLogInterface myLogObject) { myLogObject.WriteLog(); //So I can use WriteLog here. } } public class MyMainClass { public void DoSomething() { MyClass aClass = new MyClass(); MyOtherClass otherClass = new MyOtherClass(); MyLogClass.WriteLog(aClass);//MyClass can log, and have his own implementation MyLogClass.WriteLog(otherClass); //As MyOtherClass also have his own implementation on how to log. } } } 

En mi ejemplo, podría ser un desarrollador que escriba MyLogClass , y los otros desarrolladores, podrían crear las clases, y cuando quisieran iniciar sesión, implementarían la interfaz IMyLogInterface . Es como si me preguntaran qué necesitan implementar para usar el método MyLogClass WriteLog() en MyLogClass . La respuesta que encontrarán en la interfaz.

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é la interfaz

  • No tiene implementación de código predeterminado o compartido
  • Desea compartir contratos de datos (servicios web, SOA)
  • Tiene implementaciones diferentes para cada implementador de interfaz ( IDbCommand tiene SqlCommand y OracleCommand que implementan la interfaz de maneras específicas )
  • Desea admitir herencia múltiple .

Por qué abstracto

  • Tiene implementación de código predeterminado o compartido
  • Desea minimizar la duplicación de código
  • Desea admitir fácilmente el control de versiones

Una razón por la que uso interfaces es porque aumenta la flexibilidad del código. Digamos que obtuvimos un método que toma un objeto del tipo de clase Cuenta como parámetro, como por ejemplo:

  public void DoSomething(Account account) { // Do awesome stuff here. } 

El problema con esto, es que el parámetro de método está fijo hacia una implementación de una cuenta. Esto está bien si nunca necesitaras otro tipo de cuenta. Tome este ejemplo, que en su lugar usa una interfaz de cuenta como parámetro.

 public void DoSomething(IAccount account) { // Do awesome stuff here. } 

Esta solución no está fijada para una implementación, lo que significa que puedo pasarle una cuenta SuperSavingsAccount o una Cuenta Exclusiva (ambas implementando la interfaz IAccount) y obtener un comportamiento diferente para cada cuenta implementada.

En una palabra, ¡debido al polymorphism !

Si “Progtwig 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 forma, su código de 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)

  • Mire en Dependency Injection y definitivamente lea los Patrones de Diseño: Elementos del Software Reutilizable Orientado a Objetos de GOF.

enter image description here

Entonces en este ejemplo, el PowerSocket no sabe nada más sobre los otros objetos. Todos los objetos dependen de la potencia proporcionada por el 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 conocer nada más el uno del otro.

C # no tiene tipado de pato: el hecho de que usted sepa que un determinado método se implementa en un conjunto de clases concretas no significa que pueda tratarlos de la misma manera en lo que respecta a llamar a ese método. La implementación de una interfaz le permite tratar a todas las clases que la implementan como el mismo tipo de cosas, con respecto a lo que define esa interfaz.

Solo puedes heredar de una clase abstracta. Puedes heredar desde 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 básica. 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 lo tanto, una interfaz sería más adecuada.

Con una interfaz puede hacer lo siguiente:

1) Cree interfaces segregadas que ofrezcan diferentes cortes de su implementación, permitiendo una interfaz más cohesiva.

2) Permita múltiples métodos con el mismo nombre entre las interfaces, porque hey, no tiene una implementación conflictiva, solo una firma.

3) Puede versionar e instalar su interfaz independientemente de su implementación, asegurando que se cumpla un contrato.

4) Su código puede confiar en la abstracción en lugar de la concreción, lo que permite la dependency injection inteligente, incluida la inyección de pruebas Mocks, etc.

Hay muchas más razones por las que estoy seguro, estos son solo algunos.

Una clase abstracta le permite tener una base parcialmente concreta desde la que trabajar, esto no es lo mismo que una interfaz, pero tiene sus propias cualidades, como la capacidad de crear una implementación parcial utilizando el patrón de método de la plantilla.

Tanto la clase abstracta como la interfaz son contratos.

La idea de un contrato es especificar algún comportamiento. Si dice que ha implementado, ha aceptado el contrato.

La elección de abstract over interrface is.

Cualquier descendiente no abstracto de la clase abstracta implementará el contrato.

versus

Cualquier clase que implemente la interfaz implementará el contrato.

Entonces, utiliza el resumen cuando desea especificar algún comportamiento que todos los descendientes deben implementar y guardarse definiendo una interfaz separada, pero ahora todo lo que cumple con este contrato efectivamente agregado debe ser un descendiente.

Creo que ya se había dertwigdo mucha sangre al hacer estas preguntas, y muchos intentan resolver este problema explicando términos robóticos que ningún humano normal puede entender.

Entonces primero para saber por qué la interfaz y por qué abstracto necesita saber para qué son. Yo personalmente aprendí esto cuando aplicaba Factory Class. encuentra un buen tuturial en este enlace

Ahora profundicemos en la base del enlace que ya di.

Tiene una clase de vehículo que puede cambiar según los requisitos del usuario (como agregar un camión , un tanque , un avión , etc. y dado que tenemos

 public class clsBike:IChoice { #region IChoice Members public string Buy() { return ("You choose Bike"); } #endregion } 

y

 public class clsCar:IChoice { #region IChoice Members public string Buy() { return ("You choose Car"); } #endregion } 

y ambos tienen Contrato IChoice que simplemente dice que mi clase debe tener el método de compra

 public interface IChoice { string Buy(); } 

Ahora, verá, esa interfaz solo impone el método Buy() pero deja que la clase heredada decida qué hacer cuando lo implementan. Esta es la limitación de la interfaz, al usar puramente la interfaz, puede terminar repitiendo alguna tarea que podemos implementar automáticamente usando abstact. En nuestro ejemplo digamos, comprar cada vehículo tiene un descuento.

 public abstract class Choice { public abstract string Discount { get; } public abstract string Type { get; } public string Buy() { return "You buy" + Type + " with " + Discount; } public class clsBike: Choice { public abstract string Discount { get { return "10% Discount Off"; } } public abstract string Type { get { return "Bike"; } } } public class clsCar:Choice { public abstract string Discount { get { return " $15K Less"; } } public abstract string Type { get { return "Car"; } } } 

Ahora, al utilizar Factory Class, puede lograr lo mismo, pero al usar abstract, permite que la clase base ejecute el método Buy() .

En resumen: los contratos de interfaz permiten que la clase heredada realice la implementación, mientras que los Contratos de clase abstracta pueden inicializar la implementación (que puede anularse por la clase Heredar)

Las interfaces permiten al diseñador de clases hacer que los métodos disponibles sean muy claros para el usuario final. También son una parte integral del polymorphism.

No publicaré la definición de una interfaz en contra de una clase abstracta porque creo que usted conoce muy bien la teoría y supongo que conoce los principios SÓLIDOS, así que seamos prácticos.

Como sabe, las interfaces no pueden tener ningún código, por lo que la ventaja es bastante simple de entender.

si necesita inicializar la propiedad de su clase que proporciona un constructor o 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.

Por lo tanto, en general, debería preferir la clase abstracta a las interfaces cuando necesite proporcionar un constructor o cualquier código al cliente que heredará / ampliará su clase

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 digan Animal y Humano, iré a Interfaz donde, como si tuviera que entrar en detalle, diga Tigre, león y quiero relacionarme con Animal, y luego elegiré la clase Animal Abstracto.

se verá abajo

  Interface ____|____ | | Animal Human Animal (Abstract class) __|___ | | Tiger Lion