C #: Les classes abstraites doivent implémenter des interfaces?

131

Mon code de test en C #:

namespace DSnA
{
    public abstract class Test : IComparable
    {

    }
}

Résultats dans l'erreur de compilateur suivante:

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

Puisque la classe Testest une classe abstraite , pourquoi le compilateur en a-t-il besoin pour implémenter l'interface? Cette exigence ne devrait-elle pas être obligatoire uniquement pour les cours concrets?

bguiz
la source
Haha. J'ai écrit une chose puis j'ai décidé de la changer. Désolé. :)
Joel
2
Sur la base des votes négatifs et des commentaires sur la réponse acceptée, je pense que les votes négatifs proviennent de la façon dont la question est formulée. OP demande «pourquoi est-ce de cette façon», ce qui serait en dehors de la portée de stackoverflow. Ayant rencontré cela moi-même, la question est plutôt "Est-ce que je manque quelque chose? Dois-je vraiment fournir des implémentations? Cela ne va-t-il pas à l'encontre du fait qu'il s'agit d'une classe abstraite?" A quoi la réponse est "Non, vous n'avez pas à fournir d' implémentations (ce qui violerait le but d'une classe abstraite), mais voici ce que vous devez faire, pour que votre situation fonctionne."
ToolmakerSteve
J'ai trouvé un cas où vous devez fournir une implémentation. C'est là que l'interface a un paramètre facultatif. Si vous incluez la méthode comme abstraite dans la classe de base, les classes héritées ne seront pas compilées sans le paramètre facultatif (ce qui va à l'encontre de l'objectif d'un paramètre facultatif). Je viens de lancer NotImplementedException dans ce cas.
Paul McCarthy le
Ignorez mon commentaire précédent - cela n'a pas fonctionné comme prévu, le principe de la moindre surprise ne s'applique pas ici.
Paul McCarthy le

Réponses:

141

En C #, une classe qui implémente une interface est requise pour définir tous les membres de cette interface. Dans le cas d'une classe abstraite, vous définissez simplement ces membres avec le abstractmot - clé:

interface IFoo
{
    void Bar();
}

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

Ou pour le dire autrement: vous n'avez pas à "l'implémenter" (ce qui serait une terrible limitation des classes abstraites); cependant, en C #, vous devez dire au compilateur que vous passez délibérément la responsabilité à des sous-classes concrètes - et la ligne de code ci-dessus montre comment faire.

Les commentaires et les votes négatifs se plaignant que ce n'est pas une réponse à la question manquent le point. Quelqu'un venant à Stack Overflow, ayant reçu cette erreur de compilation, mais ayant une classe abstraite dans laquelle ce serait une erreur de fournir une implémentation, est bloqué sans une bonne solution - devrait écrire des méthodes d'implémentation qui ont jeté des exceptions d'exécution, un travail horrible - autour - jusqu'à ce qu'ils aient les informations ci-dessus. Que ce soit bon ou mauvais que C # nécessite cette explication est en dehors de la portée de Stack Overflow, et n'est pas pertinent pour la question ni cette réponse.

Joël
la source
2
@Ben Je viens de voir votre commentaire. Vous l'avez probablement déjà compris, mais au cas où quelqu'un d'autre en aurait besoin. Découvrez les implémentations d'interface explicite: msdn.microsoft.com/en-us/library/ms173157.aspx
Joel
2
@Joel @Ben Je ne pense pas que les interfaces explicites puissent fonctionner avec des classes abstraites. Dans le code exemple ci - dessus, changer la définition de Foola public abstract void IFoo.Bar();et vous obtenez des plaintes que « public » et « abstrait » ne sont pas modificateurs valides.
Darren Cook
8
Cela ne répond pas du tout à la question de savoir pourquoi cela est même nécessaire, étant donné qu'il s'agit d'une classe abstraite et que le compilateur doit savoir comment remplir le vide. En Java, ce n'est pas nécessaire, ce qui permet plusieurs modèles utiles tels que le modèle de décorateur sur les conteneurs ioc, par exemple Spring / JavaEE (lorsque vous devez décorer une méthode particulière d'une interface gérée). La même implémentation dans.net devrait forcer les développeurs à être très verbeux en particulier sur les grandes interfaces telles que ISession de
nhibernate
1
Les mixins d'AspectJ en sont un autre exemple. Il vous permet de mélanger des implémentations partielles de nombreuses classes abstraites dans une seule interface. Chaque classe abstraite n'a besoin que d'implémenter la méthode qu'elle souhaite implémenter. Aucune méthode abstraite stupide passe-partout comme c'est le cas si je dois recréer la même fonctionnalité dans .net
Sheepy
1
@Sheepy - C'est vrai, mais, à mon humble avis, vous ne comprenez pas ce dont le demandeur a besoin , et comment c'est, en effet, une «réponse». J'avais également la même question - parce que cela n'avait pas de sens d'être obligé de fournir une implémentation, donc j'étais coincé. La réponse est: vous n'avez pas à «l' implémenter » - mais voici ce que vous devez faire pour dire au compilateur que vous n'allez pas l'implémenter. (La question à laquelle vous [correctement] dites que ce n'est pas une réponse, ne serait pas une question de stackoverflow appropriée - elle aurait simplement été fermée comme étant hors de propos.)
ToolmakerSteve
10

Contrairement à Java, en C #: "une classe abstraite doit fournir des implémentations de tous les membres des interfaces qui sont répertoriés dans la liste des classes de base de la classe. Cependant, une classe abstraite est autorisée à mapper des méthodes d'interface sur des méthodes abstraites."

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

00jt
la source
1
Réponse super claire et super que vous fournissiez les deux situations, car vous voudrez peut-être parfois implémenter le comportement dans la classe de base
VinKel
Une question qui se pose ici est la suivante: pourquoi ces déclarations standard C # (ce qu'elles sont évidemment) doivent exister dans des classes abstraites, qui pourraient autrement être concises et plus courtes (ce qui perturbe les classes)? Dans mon projet C #, j'ai beaucoup de classes et d'interfaces abstraites - et ce que je fais la plupart du temps, c'est de copier et coller des déclarations de méthodes dans Visual Studio.
forsberg le
5

Ils n'ont pas à implémenter réellement l'interface .
Les méthodes / propriétés d'interface peuvent être abstraites ou même virtuelles. C'est donc aux sous-classes de les implémenter.

Ntziolis
la source