C #: Classes abstratas precisam implementar interfaces?

131

Meu código de teste em c #:

namespace DSnA
{
    public abstract class Test : IComparable
    {

    }
}

Resultados no seguinte erro do compilador:

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

Como a classe Testé uma classe abstrata , por que o compilador exige que ele implemente a interface? Este requisito não deveria ser obrigatório apenas para classes concretas?

bguiz
fonte
Haha Eu escrevi uma coisa e decidi mudar. Desculpe. :)
Joel
2
Com base nos votos negativos e comentários sobre a resposta aceita, acredito que os votos negativos advêm da maneira como a pergunta é formulada. O OP pergunta "por que é assim", que estaria fora do escopo do stackoverflow. Tendo encontrado isso sozinho, a pergunta é mais como "Estou perdendo alguma coisa? Preciso realmente fornecer implementações? Isso não impede o fato de ser uma classe abstrata?" Para a qual a resposta é "Não, você não precisa fornecer implementações (o que violaria o objetivo de uma classe abstrata), mas aqui está o que você precisa fazer para que sua situação funcione".
Página
Eu encontrei um caso em que você precisa fornecer uma implementação. É onde a interface possui um parâmetro opcional. Se você incluir o método como abstrato na classe base, as classes herdadas não serão compiladas sem o parâmetro opcional (o que anula o objetivo de um parâmetro opcional). Acabei de jogar NotImplementedException neste caso.
Paul McCarthy em
Ignore meu comentário anterior - ele não funcionou como esperado, o princípio da menor surpresa não se aplica aqui.
Paul McCarthy

Respostas:

141

Em C #, uma classe que implementa uma interface é necessária para definir todos os membros dessa interface. No caso de uma classe abstrata, você simplesmente define esses membros com a abstractpalavra-chave:

interface IFoo
{
    void Bar();
}

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

Ou, de outra forma: você não precisa "implementá- lo " (o que seria uma limitação terrível para as classes abstratas); no entanto, em C #, você precisa informar ao compilador que está deliberadamente passando o fanfarrão para subclasses de concreto - e a linha de código acima mostra como fazer isso.

Os comentários e votos negativos queixam-se de que essa não é uma resposta à pergunta estão perdendo o objetivo. Alguém vindo ao Stack Overflow, tendo recebido esse erro do compilador, mas tendo uma classe abstrata na qual seria um erro fornecer uma implementação, fica preso sem uma boa solução - teria que escrever métodos de implementação que gerassem exceções de tempo de execução, um trabalho horrendo -around - até que tenham as informações acima. Se é bom ou ruim que o C # exija essa explicitação, está fora do escopo do Stack Overflow e não é relevante para a pergunta nem para esta resposta.

Joel
fonte
2
@ Ben Acabei de ver seu comentário. Você provavelmente já descobriu, mas no caso de alguém precisar. Confira as Implementações explícitas da interface: msdn.microsoft.com/en-us/library/ms173157.aspx
Joel
2
@Joel @Ben Não acho que interfaces explícitas possam funcionar com classes abstratas. No código de exemplo acima, altere a definição Foopara public abstract void IFoo.Bar();e você receberá reclamações de que "público" e "abstrato" não são modificadores válidos.
Darren Cozinhe
8
Isso não responde à pergunta de por que isso é mesmo necessário, considerando que essa é uma classe abstrata e o compilador deve saber como preencher o espaço em branco. Em Java, isso não é necessário, o que permite vários padrões úteis, como o padrão decorador em contêineres ioc, por exemplo, Spring / JavaEE (quando você precisa decorar um método específico de uma interface gerenciada). O mesmo in.net implementação teria que forçar os desenvolvedores a ser muito detalhada, especialmente em interfaces grandes como ISession do nhibernate
Sheepy
1
Os mixins da AspectJ são outro exemplo. Permite combinar implementações parciais de muitas classes abstratas em uma única interface. Cada classe abstrata precisa apenas implementar o método que deseja implementar. Não mudo abstrato método clichê ficando no caminho, como é o caso, se eu sou para recriar a mesma funcionalidade em .net
Sheepy
1
@ Shehepy - Verdade, mas, IMHO, você entende mal o que o solicitante precisa , e como isso é, de fato, uma "resposta". Da mesma forma, tive a mesma pergunta - porque não fazia sentido ser necessário fornecer uma implementação, por isso fiquei preso. A resposta é: você não precisa " implementá- lo" - mas aqui está o que você precisa fazer para informar ao compilador que você não o implementará. (A pergunta que você [corretamente] dizem que isso não é uma resposta a, não seria uma questão stackoverflow apropriado -. Que teria sido simplesmente fechado como off-purpose)
ToolmakerSteve
10

Diferentemente de Java, em C #: "uma classe abstrata deve fornecer implementações de todos os membros das interfaces listadas na lista de classes base da classe. No entanto, uma classe abstrata é permitida para mapear métodos de interface em métodos abstratos."

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

00jt
fonte
1
Resposta super clara e ótimo que você forneça as duas situações, pois às vezes você também pode implementar o comportamento na classe base
VinKel
Uma questão que surge aqui é: por que essas declarações clichê em C # (que obviamente são) precisam existir em classes abstratas, que poderiam ser concisas e mais curtas (interferindo assim nas classes)? No meu projeto C #, tenho muitas classes abstratas e interfaces - e o que faço na maioria das vezes é copiar e colar declarações de métodos no Visual Studio.
forsberg
5

Eles não precisam realmente implementar a interface .
Os métodos / propriedades da interface podem ser abstratos ou mesmo virtuais. Portanto, cabe às subclasses implementá-las.

ntziolis
fonte