Par exemple, supposons que je veux un ICar
interface et que toutes les implémentations de contenir le champ Year
. Est-ce à dire que chaque mise en œuvre doit déclarer séparément Year
? Ne serait-il pas plus agréable de simplement définir ce dans l'interface?
Réponses
Trop de publicités?Bien que la plupart des autres réponses sont correctes au niveau sémantique, je trouve intéressant d'aborder ce genre de questions à partir de la mise en œuvre niveau de détails.
Une interface peut être considérée comme un ensemble de fentes, qui contiennent des méthodes. Lorsqu'une classe implémente une interface, la classe est tenu d'informer le runtime comment remplir tous les slots. Quand vous dites
interface IFoo { void M(); }
class Foo : IFoo { public void M() { ... } }
la classe dit: "lorsque vous créez une instance de moi, des trucs d'une référence à Toto.M dans la fente pour IFoo.M.
Ensuite, lorsque vous faites un appel:
IFoo ifoo = new Foo();
ifoo.M();
le compilateur génère du code qui dit que "demander à l'objet ce que la méthode est dans la fente pour IFoo.M, et d'appeler cette méthode.
Si une interface est une collection de machines à sous qui contiennent des méthodes, puis certains de ces emplacements peut également contenir les méthodes get et set d'une propriété, les méthodes get et set d'un indexeur, et de l'ajouter et de supprimer des méthodes d'un événement. Mais un champ n'est pas une méthode. Il n'y a pas de "fente" associé à un champ que vous pouvez ensuite "remplir" avec une référence à l'emplacement du champ. Et donc, les interfaces peuvent définir des méthodes, des propriétés, des indexeurs et des événements, mais pas les champs.
Les Interfaces en C# ont pour objet de définir le contrat qu'une classe d'adhérer à - pas d'une mise en oeuvre particulière.
Dans cet esprit, C# interfaces permettent de propriétés définies par l'appelant doit fournir une implémentation pour:
interface ICar
{
int Year { get; set; }
}
La mise en œuvre de classes peuvent utiliser des auto-propriétés pour simplifier la mise en œuvre, si il n'y a aucune logique associée à la propriété:
class Automobile : ICar
{
public int Year { get; set; } // automatically implemented
}
Eric Lippert cloué, je vais utiliser un autre moyen de dire ce qu'il a dit. Tous les membres d'une interface sont virtuels, et ils ont tous besoin d'être remplacée par une classe qui hérite de l'interface. Vous n'avez pas l'écrire explicitement le mot clé virtual dans la déclaration d'interface, ni utiliser le mot-clé override de la classe, ils sont implicites.
Le mot-clé virtuel est mis en œuvre .NET avec des méthodes et un soi-disant v-tableau, un tableau de pointeurs de méthode. Le mot-clé override remplit la v-table fente avec une méthode différente pointeur, l'écrasement de celle produite par la classe de base. Les propriétés, les événements et les indexeurs sont mises en œuvre que les méthodes sous le capot. Mais les champs ne sont pas. Les Interfaces peuvent donc pas contenir de champs.
Pourquoi ne pas simplement avoir un Year
de la propriété, qui est parfaitement bien?
Les Interfaces ne contiennent pas de champs, car les champs représentent une mise en œuvre spécifique de représentation des données, et de les exposer de casser l'encapsulation. Ainsi, ayant une interface avec un champ serait effectivement de codage pour une mise en place de l'interface, ce qui est un curieux paradoxe pour une interface à avoir!
Par exemple, une partie de votre Year
spécification peut exiger qu'il soit invalide pour ICar
des exécutants afin de permettre l'attribution à un Year
qui est postérieure à l'année en cours + 1 ou avant 1900. Il n'y a aucun moyen de dire que si l'on avait exposé Year
champs-de loin préférable d'utiliser des propriétés, au lieu de faire le travail ici.