2017-09-05 2 views
0

Nous implémentons généralement des interfaces explicitement quand il n'est pas correct d'accéder au membre de l'interface directement à partir de la classe d'implémentation. Le temps qu'il doit être interne ou il provoque des conflits avec la conception de l'API ou quand il augmente le risque de mauvaise utilisation des méthodes.Pourquoi est-il possible de remplacer une implémentation explicite?

membres de mise en œuvre individuellement pour plusieurs interfaces avec une logique différente est absolument découragé dans mon esprit pour que MALLETE pas ici

compilateur ne permettent pas de faire cette mise en œuvre virtuelle parce qu'il n'a pas de sens et je pense qu'il est droite. L'implémentation généralement explicite est très sensible et c'est pourquoi vous essayez de la masquer.

Cependant, je trouve comme suit de plus-riding mise en œuvre explicite (il est override pas exactement, mais son alternative tricherie)

Je trouve cela surprenant et assez décevant. Ma question est pourquoi le code suivant est autorisé et fonctionne parfaitement? Je m'attendais à avoir une erreur que l'interface est déjà implémentée explicitement.

Ceci est juste exemple de base pour reproduire le problème

static void Main(string[] args) 
{ 
    var b = new Base(); 
    ((IInterface)b).Write(); 

    var c = new Child(); 
    ((IInterface)c).Write(); 
} 
public interface IInterface 
{ 
    void Write(); 
} 
public class Base : IInterface 
{ 
    void IInterface.Write() 
    { 
     Console.WriteLine("Base"); 
    } 
} 
public class Child : Base, IInterface // hack is here. Re Implemented :/ 
{ 
    void IInterface.Write() 
    { 
     Console.WriteLine("Child"); 
    } 
} 

Outputs 

    Base 
    Child 
+0

Comment avez-vous réussi à gâcher le formatage du code comme ça? – CodeCaster

+0

Considérons un cas un peu plus compliqué, la méthode 'Write' devrait imprimer toutes les variables internes de la classe. Maintenant, si 'Child' avait plus de variables alors sûrement il devrait ré-implémenter l'interface car il pourrait contenir plus de variables que' Base'. Vous ne pouvez pas voir votre point de prévenir la ré-implémentation des interfaces. –

+0

@CodeCaster je l'ai tapé depuis mon téléphone. J'ai envoyé du texte contenant du code de mon PC à mon téléphone, puis copié collé. Donc, je n'étais pas content de mon copier coller. –

Répondre

2

Parce que les spécifications disent:

Il est une erreur de compilation pour une implémentation membre d'interface explicite pour inclure des modificateurs d'accès, et il est une erreur de compilation pour inclure les modificateurs abstraits , virtuel, override ou statique.

Pourtant, dans le polymorphisme, dit le proverbe "plus type dérivé sait mieux", des spécifications encore:

classes dérivées peuvent étendre et spécialiser les classes de base

So le type le plus dérivé qui implémente explicitement cette interface sera appelé lorsque vous appelez ce membre d'interface.

+0

Cela a du sens, je n'ai pas vu dans votre perspective. Est-il un moyen d'empêcher cela? En supposant que vous concevez une API et que vous ne pouvez pas rendre l'interface interne. –

+4

Marquez 'base Base' comme scellé. Si vous ne faites qu'exposer des interfaces pour une API, et non des classes, vous ne pouvez pas contrôler comment les développeurs vont l'utiliser. – CodeCaster

+0

Je vois, mais je voulais qu'il soit héritable, donc il peut être étendu. Je suppose que ce que je veux ne peux pas être atteint. Je pourrais utiliser à la place la classe wrapper ou utiliser des champs internes. Merci d'avoir répondu. –

0

Je vous suggère de penser à la faible translation de niveau de C# en code natif: l'héritage d'interface redéclaration, et l'un ou plusieurs de ses méthodes prépondérants, force la réécriture du VMT - Virtual Method Table (les méthodes d'interface sont virtuelles par conception). Pourquoi le code suivant est-il autorisé et fonctionne-t-il parfaitement?