C #: ¿Las clases abstractas necesitan implementar interfaces?

131

Mi código de prueba en C #:

namespace DSnA
{
    public abstract class Test : IComparable
    {

    }
}

Resultados en el siguiente error del compilador:

error CS0535: 'DSnA.Test' does not implement interface member
'System.IComparable.CompareTo(object)'

Dado que la clase Testes una clase abstracta , ¿por qué el compilador requiere que implemente la interfaz? ¿No debería ser obligatorio este requisito solo para clases concretas?

bguiz
fuente
Jaja. Escribí una cosa y luego decidí cambiarlo. Lo siento. :)
Joel
2
Basado en los votos negativos y los comentarios sobre la respuesta aceptada, creo que los votos negativos se deben a la forma en que está formulada la pregunta. OP pregunta "por qué es así", lo que estaría fuera del alcance de stackoverflow. Habiéndome encontrado con esto yo mismo, la pregunta es más como "¿Me estoy perdiendo algo? ¿Realmente tengo que proporcionar implementaciones? ¿Acaso eso no niega el punto de ser una clase abstracta?" A lo que la respuesta es "No, no tiene que proporcionar implementaciones (lo que violaría el propósito de una clase abstracta), pero esto es lo que debe hacer para que su situación funcione".
ToolmakerSteve
Encontré un caso en el que tienes que proporcionar una implementación. Es donde la interfaz tiene un parámetro opcional. Si incluye el método como abstracto en la clase base, las clases heredadas no se compilarán sin el parámetro opcional (que anula el propósito de un parámetro opcional). Acabo de lanzar NotImplementedException en este caso.
Paul McCarthy
Ignore mi comentario anterior: no funcionó como se esperaba, el principio de menor sorpresa no se aplica aquí.
Paul McCarthy

Respuestas:

141

En C #, se requiere una clase que implemente una interfaz para definir todos los miembros de esa interfaz. En el caso de una clase abstracta, simplemente define esos miembros con la abstractpalabra clave:

interface IFoo
{
    void Bar();
}

abstract class Foo : IFoo
{
    public abstract void Bar();
}

O para decirlo de otra manera: no tiene que "implementarlo" (lo que sería una limitación terrible en las clases abstractas); sin embargo, en C #, tiene que decirle al compilador que está pasando deliberadamente el dinero a subclases concretas, y la línea de código anterior muestra cómo hacerlo.

Los comentarios y votos negativos quejándose de que esto no es una respuesta a la pregunta están perdiendo el punto. Alguien que viene a Stack Overflow, que recibió este error de compilación, pero que tiene una clase abstracta en la que sería un error proporcionar una implementación, está atrapado sin una buena solución: tendría que escribir métodos de implementación que arrojaran excepciones de tiempo de ejecución, un trabajo horrendo -alrededor - hasta que tengan la información anterior. Si es bueno o malo que C # requiera esta explicidad está fuera del alcance de Stack Overflow, y no es relevante para la pregunta ni esta respuesta.

Joel
fuente
2
@Ben Acabo de ver tu comentario. Probablemente ya lo haya descubierto, pero en caso de que alguien más lo necesite. Consulte las implementaciones explícitas de la interfaz: msdn.microsoft.com/en-us/library/ms173157.aspx
Joel
2
@Joel @Ben No creo que las interfaces explícitas puedan funcionar con clases abstractas. En el código de ejemplo anterior, cambie la definición Fooa public abstract void IFoo.Bar();y obtendrá quejas de que "público" y "abstracto" no son modificadores válidos.
Darren Cook, el
8
Esto no responde a la pregunta de por qué esto es incluso necesario, teniendo en cuenta que se trata de una clase abstracta y que el compilador debe saber cómo completar el espacio en blanco. En Java, esto no es necesario, lo que permite varios patrones útiles, como el patrón de decorador en contenedores ioc, por ejemplo, Spring / JavaEE (cuando necesita decorar un método particular de una interfaz administrada). Lo mismo in.net aplicación tendría que obliga a los desarrolladores a ser muy detallado, especialmente en las grandes interfaces como ISession de nhibernate
Sheepy
1
Los mixins de AspectJ son otro ejemplo. Le permite mezclar implementaciones parciales de muchas clases abstractas en una sola interfaz. Cada clase abstracta solo necesita implementar el método que desea implementar. Ningún método abstracto tonto se interpone en el camino como es el caso si voy a recrear la misma funcionalidad en .net
Sheepy
1
@Sheepy: es cierto, pero, en mi humilde opinión, no entiendes lo que el autor de la pregunta necesita y cómo es, de hecho, una "respuesta". También tuve la misma pregunta, porque no tenía sentido que se me pidiera que proporcionara una implementación, así que me quedé estancado. La respuesta es: no tiene que " implementarlo ", pero esto es lo que debe hacer para decirle al compilador que no lo va a implementar. (La pregunta a la que usted dice [correctamente] que esto no es una respuesta, no sería una pregunta apropiada de stackoverflow, simplemente se habría cerrado como fuera de propósito.)
ToolmakerSteve
10

A diferencia de Java, en C #: "una clase abstracta debe proporcionar implementaciones de todos los miembros de las interfaces que se enumeran en la lista de la clase base de la clase. Sin embargo, una clase abstracta puede mapear métodos de interfaz en métodos abstractos".

https://msdn.microsoft.com/en-us/library/Aa664595(v=VS.71).aspx

00jt
fuente
1
Respuesta súper clara y genial que proporcione ambas situaciones, ya que a veces también puede querer implementar el comportamiento en la clase base
VinKel
Una pregunta que surge aquí es: ¿por qué estas declaraciones repetitivas de C # (que obviamente son) deben existir en clases abstractas, que de lo contrario podrían ser concisas y más cortas (lo que desordenaría las clases)? En mi proyecto C # tengo muchas clases abstractas e interfaces, y lo que hago la mayoría del tiempo es copiar y pegar declaraciones de métodos en Visual Studio.
forsberg
5

No tienen que implementar realmente la interfaz .
Los métodos / propiedades de la interfaz pueden ser abstractos o incluso virtuales también. Entonces depende de las subclases implementarlas realmente.

ntziolis
fuente