2009-09-17 4 views
1

J'ai vu ce code et quelques questions:Héritage d'une classe, qu'est-ce que cela fait?

public class MyClassB : MyClassA, IMyClass 
{ 
    void IMyClass.InsertUser(User user) { } 
} 

Pourquoi ont-ils préfixer l'interface, IMyClass et non juste faire:

void InsertUser(User user) { } 

ou peut-être faire

void new InsertUser(User user) 

En outre, puisque vous héritez de MyClassA (qui implémente l'interface IMyClass), pourquoi nous voyons:

public class MyClassB : MyClassA, IMyClass { } 

Répondre

10

Juste

void InsertUser(User user) 

ne fonctionnerait pas comme cela déclarer une méthode privée. La version avec le préfixe s'appelle explicit interface implementation. Il rend la méthode disponible uniquement via l'interface. L'une de ses principales utilisations est de vous permettre de mettre en œuvre plusieurs interfaces qui contiennent la même méthode. Le meilleur exemple de ceci est IEnumerable<T> qui s'étend IEnumerable - les deux ont une méthode GetEnumerator(), mais avec différents types de retour. Typiquement, vous faites:

public class Foo : IEnumerable<T> 
{ 
    // Implicit interface implementation 
    public IEnumerator<T> GetEnumerator() 
    { 
     // Real work 
    } 

    // Explicit interface implementation 
    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); // Calls method above 
    } 
} 

En ce qui concerne redéclarant l'interface, cela est nécessaire si vous êtes également réimplémentant l'interface qui il semble que vous faites ici. Je suppose que MyClassA implémente l'interface avec une méthode non-virtuelle (ou explicitement), ce qui signifie qu'elle ne peut pas être substituée dans la classe dérivée ... donc pour réimplémenter l'interface, vous devez la redéclarer.

Personnellement, j'essaierais d'éviter cette situation lorsque cela est possible - cela peut conduire à toutes sortes de problèmes lorsque la méthode qui est appelée dépend exactement de la façon dont vous "regardez" l'objet en question. Il vaudrait mieux que MyClassA implémente l'interface avec une méthode virtuelle que MyClassB pourrait alors surcharger.

+0

donc la méthode dans MyClassA doit être marquée virtuelle, et puis je viens de la surcharger? C'est ce que j'ai l'habitude de faire! – mrblah

0

C'est un explicit interface implementation.

Très probablement c'est comme ça parce que le code a laissé l'assistant VS pour lui/elle. C'est une fonctionnalité permettant de désambiguïser des méthodes avec des signatures similaires.

0

Le préfixe signifie que l'interface a été implémentée explicitement. Lorsque vous avez une instance de votre classe, vous ne serez pas capable d'appeler la méthode directement, vous devrez à la place lancer l'instance dans l'interface pour appeler la méthode.

Il y a deux raisons à cela. Cette première étape consiste à implémenter plusieurs interfaces ayant le même nom de méthode, mais qui doivent se comporter de différentes manières. La seconde est quand vous avez besoin d'implémenter une interface mais que vous ne voulez pas que les méthodes soient généralement disponibles pour l'utilisateur sauf si elles le veulent explicitement

1

Votre première question a déjà reçu une réponse. Voici un aller aux autres:

void new InsertUser(User user) 

Cela créerait une nouvelle implémentation de InsertUser qui voilent celui de la classe de base.Alors:

myClassBInstance.InsertUser(user); 

appelleraient MyClassB.InsertUser(), alors que

MyClassA myClassAInstance = myClassBInstance; 
myClassAInstance.InsertUser(user); 

appellerait MyClassA.InsertUser().

Ceci est en contraste avec l'implémentation d'interface explicite, qui seulement sera disponible via l'interface. Puis

IMyClassA myIClassAInstance = myClassBInstance; 
myIClassAInstance.InsertUser(user); 

appelleraient MyClassB.InsertUser, alors que:

myClassBInstance.InsertUser(user); 

... appelleraient MyClassA.InsertUser().

Maintenant, pour la dernière question: Si MyClassA implémente IMyClass, la déclaration:

public class MyClassB : MyClassA, IMyClass { } 

est en fait redondant (mais légal). Comme vous le supposez, MyClassB hérite de l'interface de MyClassA. Ainsi, la déclaration

public class MyClassB : MyClassA { } 

serait équivalente.

0

La raison pour laquelle vous devez taper le nom de l'interface ou le remplacer est que MyClassA utilise également l'interface IMyClass, ce qui signifie qu'elle implémente la méthode InsertCustomer.