¿Tiene sentido definir una interfaz si ya tengo una clase abstracta?

12

Tengo una clase con alguna funcionalidad predeterminada / compartida. Yo uso abstract class para ello:

public interface ITypeNameMapper
{
    string Map(TypeDefinition typeDefinition);
}

public abstract class TypeNameMapper : ITypeNameMapper
{
    public virtual string Map(TypeDefinition typeDefinition)
    {
        if (typeDefinition is ClassDefinition classDefinition)
        {
            return Map(classDefinition);
        }
        ...

        throw new ArgumentOutOfRangeException(nameof(typeDefinition));
    }

    protected abstract string Map(ClassDefinition classDefinition);
}

Como puede ver, también tengo la interfaz ITypeNameMapper . ¿Tiene sentido definir esta interfaz si ya tengo una clase abstracta TypeNameMapper o abstract class es suficiente?

TypeDefinition en este ejemplo mínimo también es abstracto.

    
pregunta Konrad 26.07.2018 - 15:17

5 respuestas

31

Sí, porque C # no permite la herencia múltiple excepto con interfaces.

Entonces, si tengo una clase que puede ser TypeNameMapper y SomethingelseMapper, puedo hacerlo:

class MultiFunctionalClass : ITypeNameMapper, ISomethingelseMapper 
{
    private TypeNameMapper map1
    private SomethingelseMapper map2

    public string Map(TypeDefinition typeDefinition) { return map1.Map(typeDefintion);}

    public string Map(OtherDef otherDef) { return map2.Map(orderDef); }
}
    
respondido por el Ewan 26.07.2018 - 15:23
1

Las interfaces y las clases abstractas tienen diferentes propósitos:

  • Interfaces definen las API y pertenecen a los clientes, no a las implementaciones.
  • Si las clases comparten implementaciones, puede beneficiarse de una clase abstracta .

En su ejemplo, interface ITypeNameMapper define las necesidades de los clientes y abstract class TypeNameMapper no agrega ningún valor.

    
respondido por el Geoffrey Hale 27.07.2018 - 01:15
0

Se creó todo el concepto de interfaces para admitir una familia de clases que tienen una API compartida.

Esto indica explícitamente que cualquier uso de una interfaz implica que hay (o se espera que haya) más de una implementación de su especificación.

Los marcos DI han enturbiado las aguas aquí, ya que muchos de ellos requieren una interfaz a pesar de que solo habrá una implementación; para mí esto es una sobrecarga irrazonable para lo que en la mayoría de los casos es solo un medio más complejo y más lento de llamar nuevos. , pero es lo que es.

La respuesta está en la pregunta en sí. Si tiene una clase abstracta, se está preparando para la creación de más de una clase derivada con una API común. Por lo tanto, el uso de una interfaz está claramente indicado.

    
respondido por el Rodney P. Barbati 26.07.2018 - 19:56
0

Si queremos responder explícitamente a la pregunta, el autor dice "¿Tiene sentido definir esta interfaz si ya tengo una clase abstracta TypeNameMapper o la clase abstracta es suficiente?"

La respuesta es sí y no: sí, debe crear la interfaz aunque ya tenga la clase base abstracta (porque no debería referirse a la clase base abstracta en ningún código de cliente) y no, porque debería no haber creado la clase base abstracta en ausencia de una interfaz.

Es evidente que no has pensado lo suficiente en la API que estás intentando construir. Primero cree la API, luego proporcione una implementación parcial si lo desea. El hecho de que su clase base abstracta sí compruebe el código es suficiente para decirle que no es la abstracción correcta.

Como en la mayoría de las cosas en OOD, cuando está en el surco y su modelo de objeto se hace bien, su código le informará sobre lo que vendrá después. Comience con una interfaz, implemente esa interfaz en las clases que la necesita. Si se encuentra escribiendo un código similar, extráigalo en una clase base abstracta: si la interfaz es importante, la clase base abstracta es solo una ayuda y puede haber más de una.

    
respondido por el Rodney P. Barbati 05.08.2018 - 23:11
-1

Esto es bastante difícil de responder sin conocer el resto de la aplicación.

Suponiendo que está utilizando algún tipo de modelo DI y ha diseñado su código para que sea lo más extensible posible (para que pueda agregar fácilmente TypeNameMapper fácilmente), diría que sí.

Razones para:

  • Lo obtienes de forma gratuita, ya que la clase base implementa el interface , no necesitas preocuparte por eso en ninguna implementación secundaria
  • La mayoría de los marcos de IoC y las bibliotecas de Mocking esperan interface s. Si bien muchos de ellos trabajan con clases abstractas, no siempre es así, y creo que seguir el mismo camino que el otro 99% de los usuarios de una biblioteca, siempre que sea posible.

Razones contra:

  • Hablando estrictamente (como lo has señalado), REALMENTE no necesitas
  • Si el class / interface cambia, hay una pequeña sobrecarga adicional

A fin de cuentas, diría que debes crear el interface . Las razones en contra son bastante insignificantes pero, si bien es posible utilizar resúmenes en burlas e IoC, a menudo es mucho más fácil con las interfaces. Sin embargo, en última instancia, no criticaría el código de un colega si fueran por el otro lado.

    
respondido por el Liath 26.07.2018 - 15:24

Lea otras preguntas en las etiquetas