Pourquoi ne puis-je pas avoir des membres d’interface protégés?

Quel est l’argument contre la déclaration des membres d’access protégé sur les interfaces? Ceci, par exemple, n’est pas valide:

public interface IOrange { public OrangePeel Peel { get; } protected OrangePips Seeds { get; } } 

Dans cet exemple, l’interface IOrange garantirait que les développeurs fournissent au moins une instance OrangePips à leurs héritiers. Si l’implémenteur le souhaitait, ils pourraient étendre la scope à tous les public :

 public class NavelOrange : IOrange { public OrangePeel Peel { get { return new OrangePeel(); } } protected OrangePips Seeds { get { return null; } } } public class ValenciaOrange : IOrange { public OrangePeel Peel { get { return new OrangePeel(); } } public OrangePips Seeds { get { return new OrangePips(6); } } } 

L’intention des membres protected sur les interfaces est de fournir un contrat de support pour les héritiers (sous-classes), par exemple:

 public class SpecialNavelOrange : NavelOrange { ... // Having a seed value is useful to me. OrangePips seeds = this.Seeds; ... } 

(Certes, cela ne fonctionnerait pas pour les struct )

Je ne vois pas beaucoup de cas pour internal modificateurs private ou internal dans les interfaces, mais la prise en charge protected modificateurs public et protected semble tout à fait raisonnable.


Je vais essayer d’expliquer l’utilité des membres protected sur les interface en les séparant entièrement de l’ interface :

Imaginons un nouveau mot clé C #, support , pour appliquer les contrats héritiers, afin que nous déclarions les choses comme suit:

 public support IOrangeSupport { OrangePips Seeds { get; } } 

Cela nous permettrait de contracter des classes pour fournir des membres protégés à leurs héritiers:

 public class NavelOrange : IOrange, IOrangeSupport { public OrangePeel Peel { get { return new OrangePeel(); } } protected OrangePips Seeds { get { return null; } } } 

Cela n’est pas particulièrement utile, car les classes impliqueraient déjà ce contrat en fournissant les membres protected en premier lieu.

Mais alors nous pourrions aussi faire ceci:

 public interface IOrange : IOrangeSupport { ... } 

IOrangeSupport ainsi IOrangeSupport à toutes les classes qui implémentent IOrange et les obligeant à fournir protected membres protected particuliers – ce que nous ne pouvons pas faire actuellement.

Je pense que tout le monde a martelé le point d’une interface n’ayant que des membres publics, pas de détails d’implémentation. Ce que vous recherchez est une classe abstraite .

 public interface IOrange { OrangePeel Peel { get; } } public abstract class OrangeBase : IOrange { protected OrangeBase() {} protected abstract OrangePips Seeds { get; } public abstract OrangePeel Peel { get; } } public class NavelOrange : OrangeBase { public override OrangePeel Peel { get { return new OrangePeel(); } } protected override OrangePips Seeds { get { return null; } } } public class ValenciaOrange : OrangeBase { public override OrangePeel Peel { get { return new OrangePeel(); } } protected override OrangePips Seeds { get { return new OrangePips(6); } } } 

Edit: Il est juste de dire que si nous avons un PlasticOrange qui dérive d’une classe Ornament, il ne peut implémenter qu’IOrange et non la méthode protégée Seeds. C’est bon. Une interface par définition est un contrat entre un appelant et un object, et non entre une classe et ses sous-classes. La classe abstraite est aussi proche que nous en venons à ce concept. Et c’est bien. Ce que vous proposez essentiellement, c’est une autre construction dans le langage à travers laquelle nous pouvons passer des sous-classes d’une classe de base à une autre sans casser la construction. Pour moi, cela n’a pas de sens.

Si vous créez une sous-classe d’une classe, la sous-classe est une spécialisation de la classe de base. Il doit être pleinement conscient de tous les membres protégés de la classe de base. Mais si vous voulez soudainement désactiver la classe de base, cela n’a aucun sens que la sous-classe fonctionne avec une autre IOrange.

Je suppose que vous avez une bonne question, mais cela semble être une affaire cruciale et je ne vois aucun avantage à en être honnête.

Je ne vois pas pourquoi on voudrait ça. Si vous souhaitez que la classe dérivée fournisse une implémentation d’une méthode particulière, optez pour les classes de base abstraites. Les interfaces ne sont que cela – des interfaces. Un contrat public, rien d’autre. Pensez à l’interface comme à la spécification, qui décrit comment la mise en œuvre doit se tourner vers le monde extérieur. Une spécification pour une prise à deux broches n’indique pas (du moins je suppose que) sa structure interne. Il doit juste être compatible avec l’interface avec une prise de courant. Plug http://www.made-in-china.com/image/2f0j00MCetlafAYTWcM/Two-Round-pin-Plug-with-Power-Wire.jpg

Parce que ça n’a pas de sens. Une interface est un contrat exposé publiquement. Je suis un IThing, donc je vais effectuer des méthodes IThing si demandé. Vous ne pouvez pas demander à un IThing de confirmer qu’il exécute des méthodes dont il ne peut pas vous parler.

Des interfaces existent pour permettre aux personnes d’accéder à votre classe sans savoir quelle est la mise en œuvre concrète. Il sépare complètement la mise en œuvre du contrat de transmission de données.

Par conséquent, tout dans une interface doit être public. Les membres non publics ne sont utiles que si vous avez access à l’implémentation et ne consortingbuent donc pas de manière significative à la définition d’une interface.

Les membres d’interface sont une API publique. des choses comme protected etc sont des détails d’implémentation – et les interfaces n’ont aucune implémentation. Je soupçonne que ce que vous recherchez est une implémentation d’interface explicite:

 public class NavelOrange : IOrange { public OrangePeel Peel { get { return new OrangePeel(); } } OrangePips IOrange.Seeds { get { return null; } } } 

Une interface est un contrat qui promet certaines fonctionnalités aux clients. En d’autres termes, le but d’une interface est de pouvoir y insérer un type et de le faire circuler comme cela pour coder les fonctionnalités requirejses par cette interface. Comme le code client d’un type ne peut pas accéder aux membres protégés de ce type, cela n’a aucun sens de déclarer des éléments protégés dans une interface.

Une interface est comme la forme d’une clé.

entrer la description de l'image ici

Ce n’est pas la clé.

Ce n’est pas la serrure.

C’est juste le sharepoint contact étroit.

Pour cette raison, tous les membres de l’interface (qui définissent la forme de la clé) doivent être publics.

Pour qu’une clé ouvre une serrure, il est important qu’elles partagent la même forme.

En rendant la forme (l’interface) publique , vous pouvez laisser les autres créer des verrous compatibles ou des clés compatibles.

Sinon, le rendant (l’interface) interne, vous ne permettrez pas aux autres de créer des verrous compatibles ou des clés compatibles.

Une interface est tout ce que peut faire un certain object, donc quand on utilise une classe qui implémente cette interface, le développeur s’attend à ce que tous les membres soient implémentés, donc le modificateur d’access protégé ne veut rien dire pour les interfaces.

Il y a un bon jugement dans la conception actuelle des interfaces, c’est-à-dire qu’il offre une plus grande flexibilité aux développeurs. Rappelez-vous que très souvent, les interfaces sont écrites par des programmeurs et que les implémenteurs sont différents. Faire respecter la mise en œuvre serait inutilement sévère.

En implémentant une interface, le type indique qu’il prend en charge un ensemble spécifique de méthodes. Si l’une de ces méthodes n’était pas publique, elle ne serait pas disponible pour les appelants et le type ne prendrait donc pas en charge l’interface comme indiqué.

Une interface ne contient que des membres publics. Protégé signifie que tout ce que vous déclarez n’est disponible que pour les instances de classes et de classes dérivées.

Toute classe qui implémente une interface .net devra inclure des implémentations de tous les membres de l’interface. De plus, toute classe peut exposer à une classe dérivée quels que soient les membres de son choix. Exiger qu’une implémentation d’une interface contienne un membre utilisable uniquement à partir de classes dérivées ne serait d’aucune utilité, à moins que (1) un tel membre puisse être visible par quelque chose en dehors de l’interface ou (2) les membres qu’ils ne définissaient pas eux-mêmes. Si les interfaces étaient autorisées à inclure des classes nestedes (qui pouvaient accéder aux membres protected des interfaces), alors protected membres d’interface protected auraient un sens. En effet, ils pourraient être très utiles si une classe nestede dans une interface pouvait définir des méthodes d’extension pour cette interface. Malheureusement, aucune installation de ce type n’existe.

BTW, même sans être capable d’imbriquer des classes dans les interfaces, il serait toujours utile d’appliquer un modificateur d’access internal aux membres de l’interface, avec pour effet que seul l’assembly où l’interface est définie serait capable de définir les implémentations.