Héritage de l’interface C # vers la classe abstraite

Supposons que j’ai une interface telle que définie ci-dessous:

public interface IFunctionality { void Method(); } 

et j’implémente cette interface pour une classe abstraite comme indiqué ci-dessous:

 public abstract class AbstractFunctionality: IFunctionality { public void Method() { Console.WriteLine("Abstract stuff" + "\n"); } } 

encore une fois j’ai une classe concrète qui hérite de la classe abstraite comme ci-dessous:

 public class ConcreteFunctionality: AbstractFunctionality { public void Method() { Console.WriteLine("Concrete stuff" + "\n"); } } 

Maintenant, j’ai le code suivant,

 ConcreteFunctionality mostDerived = new ConcreteFunctionality(); AbstractFunctionality baseInst = mostDerived; IFunctionality interfaceInst = mostDerived; mostDerived.Method(); baseInst.Method(); interfaceInst.Method(); 

La sortie que j’obtiens après l’exécution de ce matériel est la suivante.

 Concrete stuff Abstract stuff Abstract stuff 

Mais ce que je m’attendais à ce que le résultat soit “Concrete Stuff” dans les trois cas, ce que je fais ici, c’est d’atsortingbuer la référence de ConcreteFunctionality aux variables de type AbstractFunctionality et IFunctionality .

Qu’est-ce qui se passe en interne? Veuillez préciser

Ici:

 public class ConreteFunctionality:AbstractFunctionality { public void Method() { Console.WriteLine("Concrete stuff" + "\n"); } } 

… vous ne remplacez pas la méthode existante . Vous créez une nouvelle méthode qui cache celle existante. (Vous devriez également recevoir un avertissement vous suggérant d’utiliser le new modificateur si vous voulez vraiment ce comportement.) L’interface a été implémentée dans AbstractFunctionality , de sorte que la table de mappage d’interface fait référence à la méthode de cette classe.

Maintenant, si vous réimplémentez l’interface:

 public class ConcreteFunctionality : AbstractFunctionality, IFunctionality 

… alors le mappage d’interface fera référence à la méthode dans ConcreteFunctionality et vous obtiendrez le comportement que vous attendez pour l’appel via l’ interface (votre troisième appel), mais vous aurez toujours l’implémentation dans AbstractFunctionality pour votre deuxième appel.

Il serait généralement plus propre et plus sain de rendre la méthode virtuelle dans AbstractFunctionality et de la remplacer dans ConcreteFunctionality . De cette façon, il utilisera l’implémentation ConcreteFunctionality dans tous les cas.

Vous devez définir des classes comme suit:

 public abstract class AbstractFunctionality:IFunctionality { public virtual void Method() { Console.WriteLine("Abstract stuff" + "\n"); } } public class ConreteFunctionality:AbstractFunctionality { public override void Method() { Console.WriteLine("Concrete stuff" + "\n"); } } 

Comme vous n’avez pas remplacé Method () dans ConreteFunctionality, l’environnement d’exécution exécute Method () associé à l’object AbstractFunctionality car il ne peut pas appliquer le polymorphism dynamic ici. L’introduction de virtual et override crée l’environnement d’exécution pour exécuter la méthode de substitution dans la classe enfant.

Vous override mots clés virtual et de override . Sans cela, vous n’obtenez pas de fonctions virtuelles.

Vous pouvez marquer Method dans AbstractFunctionality comme virtual et marquer la Method dans ConreteFunctionality comme override . Comme Mihirj l’a montré.

Des problèmes similaires sont abordés – Pourquoi les méthodes d’interface C # ne sont-elles pas déclarées abstraites ou virtuelles?