c# méthode - Quelle est la différence entre une fonction abstraite et une fonction virtuelle?




classe virtual (18)

De la vue générale orientée objet:

En ce qui concerne la méthode abstraite : Quand vous mettez une méthode abstraite dans la classe parente, vous dites aux classes enfants: Hey notez que vous avez une signature de méthode comme celle-ci. Et si vous voulez l'utiliser, vous devez implémenter le vôtre!

En ce qui concerne la fonction virtuelle : Quand vous mettez une méthode virtuelle dans la classe parent, vous dites aux classes dérivées: Hey, il y a une fonctionnalité ici qui fait quelque chose pour vous. Si cela vous est utile, utilisez-le. Si non, remplacez ceci et implémentez votre code, même vous pouvez utiliser mon implémentation dans votre code!

c'est une philosophie à propos de différent entre ce concept deux dans General OO

Quelle est la différence entre une fonction abstraite et une fonction virtuelle? Dans quels cas est-il recommandé d'utiliser virtuel ou abstrait? Quelle est l'approche la plus correcte?


Les méthodes abstraites sont toujours virtuelles. Ils ne peuvent pas avoir une implémentation.

C'est la principale différence.

Fondamentalement, vous utiliseriez une méthode virtuelle si vous avez l'implémentation 'par défaut' et que vous voulez permettre aux descendants de changer son comportement.

Avec une méthode abstraite, vous forcez les descendants à fournir une implémentation.


explication: avec des analogies. J'espère que cela vous aidera.

Le contexte

Je travaille au 21ème étage d'un immeuble. Et je suis paranoïaque à propos du feu. De temps en temps, quelque part dans le monde, un feu brûle dans un gratte-ciel. Mais heureusement, nous avons un manuel d'instructions quelque part ici sur ce qu'il faut faire en cas d'incendie:

Escalier de secours()

  1. Ne pas recueillir d'effets personnels
  2. Marcher pour échapper à l'incendie
  3. Sortez du bâtiment

Ceci est essentiellement une méthode virtuelle appelée FireEscape ()

Méthode virtuelle

Ce plan est plutôt bon dans 99% des cas. C'est un plan de base qui fonctionne. Mais il y a 1% de chance que l'issue de secours soit bloquée ou endommagée auquel cas vous êtes complètement foutu et vous deviendrez grillé à moins que vous ne preniez des mesures drastiques. Avec les méthodes virtuelles, vous pouvez faire exactement cela: vous pouvez remplacer le plan FireEscape () de base avec votre propre version du plan:

  1. Courir à la fenêtre
  2. Sauter par la fenêtre
  3. Parachute en toute sécurité vers le bas

En d'autres termes, les méthodes virtuelles fournissent un plan de base qui peut être remplacé si nécessaire . Les sous-classes peuvent remplacer la méthode virtuelle de la classe parente si le programmeur le juge approprié.

Méthodes abstraites

Toutes les organisations ne sont pas bien forées. Certaines organisations ne font pas d'exercices d'incendie. Ils n'ont pas de politique globale d'évasion. Chaque homme est pour lui-même. La direction n'est intéressée que par une telle politique existante.

En d'autres termes, chaque personne est obligée de développer sa propre méthode FireEscape (). Un gars va sortir de l'escalier de secours. Un autre gars va parachuter. Un autre type utilisera la technologie de propulsion de fusée pour s'envoler du bâtiment. Un autre gars va descendre en rappel. La direction ne se soucie pas de savoir comment vous échapper, tant que vous avez un plan FireEscape () de base - si ce n'est pas le cas, vous pouvez être assuré que la santé et la sécurité au travail descendront sur l'organisation comme une tonne de briques. C'est ce que l'on entend par une méthode abstraite.

Quelle est la différence entre les deux?

Méthode abstraite: les sous-classes sont obligées d'implémenter leur propre méthode FireEscape. Avec une méthode virtuelle, vous avez un plan de base qui vous attend, mais vous pouvez choisir d'implémenter le vôtre si ce n'est pas suffisant.

Ce n'était pas si difficile, n'est-ce pas?


Il n'y a rien d'appeler la classe virtuelle en C #.

Pour les fonctions

  1. La fonction abstraite n'a que la signature, la classe de lecteur doit remplacer la fonctionnalité.
  2. La fonction virtuelle contiendra la partie de la fonctionnalité que la classe de lecteur peut ou ne peut pas remplacer en fonction de l'exigence

Vous pouvez décider avec votre condition.


Une fonction abstraite ne peut pas avoir de fonctionnalité. Vous êtes en train de dire que toute classe enfant DOIT donner sa propre version de cette méthode, mais il est trop général pour essayer même de l'implémenter dans la classe parente.

Une fonction virtuelle , c'est essentiellement dire look, voici la fonctionnalité qui peut ou ne peut pas être assez bon pour la classe enfant. Donc, si cela est suffisant, utilisez cette méthode, sinon, remplacez-moi, et fournissez vos propres fonctionnalités.


J'ai vu dans certains endroits la méthode abstraite est définie comme ci-dessous. **

"Une méthode abstraite doit avoir à implémenter dans la classe enfant"

** J'ai senti que c'était comme.

Il n'est pas nécessaire qu'une méthode abstraite doive être implémentée dans une classe enfant, si la classe enfant est également abstraite .

1) Une méthode abstraite ne peut pas être une méthode privée. 2) Une méthode abstraite ne peut pas être implémentée dans la même classe abstraite.

Je dirais que si nous implémentons une classe abstraite, vous devez remplacer les méthodes abstraites de la classe abstraite de base. Parce que .. L'implémentation de la méthode abstraite est avec le mot-clé override . Similaire à la méthode virtuelle.

Il n'est pas nécessaire qu'une méthode virtuelle soit implémentée dans une classe héritée.

                                 ----------CODE--------------

public abstract class BaseClass
{
    public int MyProperty { get; set; }
    protected abstract void MyAbstractMethod();

    public virtual void MyVirtualMethod()
    {
        var x = 3 + 4;
    }

}
public abstract class myClassA : BaseClass
{
    public int MyProperty { get; set; }
    //not necessary to implement an abstract method if the child class is also abstract.

    protected override void MyAbstractMethod()
    {
        throw new NotImplementedException();
    }
}
public class myClassB : BaseClass
{
    public int MyProperty { get; set; }
    //You must have to implement the abstract method since this class is not an abstract class.

    protected override void MyAbstractMethod()
    {
        throw new NotImplementedException();
    }
}

Vous utilisez essentiellement une méthode virtuelle lorsque vous voulez que les héritiers étendent la fonctionnalité SI ils le souhaitent.

Vous utilisez des méthodes abstraites lorsque vous voulez que les héritiers implémentent la fonctionnalité (et dans ce cas ils n'ont pas le choix)


La réponse a été fournie un certain nombre de fois, mais la question de savoir quand utiliser chacun est une décision au moment du design. Je verrais comme une bonne pratique d'essayer de regrouper des définitions de méthodes communes en interfaces distinctes et de les placer dans des classes à des niveaux d'abstraction appropriés. Le vidage d'un ensemble commun de définitions de méthodes abstraites et virtuelles dans une classe rend la classe impossible à distinguer lorsqu'il est préférable de définir une classe non abstraite qui implémente un ensemble d'interfaces concises. Comme toujours, cela dépend de ce qui convient le mieux aux besoins spécifiques de vos applications.


La plupart des exemples ci-dessus utilisent du code - et ils sont très très bons. Je n'ai pas besoin d'ajouter à ce qu'ils disent, mais ce qui suit est une explication simple qui utilise des analogies plutôt que des termes techniques / de code.

Explication simple - Explication en utilisant des analogies

Méthode abstraite

Pensez George W Bush. Il dit à ses soldats: "Allez combattre en Irak". Et c'est tout. Tout ce qu'il a spécifié, c'est que le combat doit être fait. Il ne précise pas exactement comment cela va se passer. Mais je veux dire, vous ne pouvez pas simplement sortir et "se battre": qu'est-ce que cela signifie exactement? est-ce que je me bats avec un B-52 ou mon derringer? Ces détails spécifiques sont laissés à quelqu'un d'autre. C'est une méthode abstraite.

Méthode virtuelle

David Petraeus est haut dans l'armée. Il a défini ce que signifie combattre:

  1. Trouver l'ennemi
  2. Neutralisez-le.
  3. Avoir une bière après

Le problème est que c'est une méthode très générale. C'est une bonne méthode qui fonctionne, mais parfois n'est pas assez spécifique. La bonne chose pour Petraeus est que ses ordres ont une marge de manœuvre - il a permis à d'autres de changer sa définition de "combat", selon leurs exigences particulières.

Job privé Bloggs lit la commande de Petraeus et obtient la permission d'implémenter sa propre version de combat, en fonction de ses exigences particulières:

  1. Trouvez l'ennemi.
  2. Tuez-le dans la tête.
  3. Rentrer chez soi
  4. Avoir de la bière.

Nouri al Maliki reçoit également les mêmes ordres de Petraeus. Il doit se battre aussi. Mais il est un politicien, pas un homme d'infanterie. Évidemment, il ne peut pas tourner autour de ses ennemis politiques dans la tête. Parce que Petraeus lui a donné une méthode virtuelle, alors Maliki peut implémenter sa propre version de la méthode de combat, selon ses circonstances particulières:

  1. Trouvez l'ennemi.
  2. Faites-le arrêter avec des accusations inventées par BS.
  3. Rentrer chez soi
  4. Avoir de la bière.

En d'autres termes, une méthode virtuelle fournit des instructions standard - mais ce sont des instructions générales, qui peuvent être rendues plus spécifiques par les gens de la hiérarchie de l'armée, en fonction de leurs circonstances particulières.

La différence entre les deux

  • George Bush ne prouve aucun détail de mise en œuvre. Cela doit être fourni par quelqu'un d'autre. C'est une méthode abstraite.

  • Petraeus, quant à lui, fournit des détails sur la mise en œuvre, mais il a donné la permission à ses subordonnés de passer outre ses ordres avec leur propre version, s'ils peuvent trouver quelque chose de mieux.

J'espère que cela pourra aider.


Fonction abstraite (méthode):

● Une méthode abstraite est une méthode qui est déclarée avec le mot clé abstract.

● Il n'a pas de corps.

● Il devrait être implémenté par la classe dérivée.

● Si une méthode est abstraite, la classe doit être abstraite.

fonction virtuelle (méthode):

● Une méthode virtuelle est la méthode qui est déclarée avec le mot clé virtual et elle peut être remplacée par la méthode de la classe dérivée en utilisant le mot-clé override.

● Il appartient à la classe dérivée de la remplacer ou non.


La liaison est le processus de mappage d'un nom à une unité de code.

La liaison tardive signifie que nous utilisons le nom, mais différons le mappage. En d'autres termes, nous créons / mentionnons le nom en premier, et laissons un processus ultérieur gérer le mappage du code à ce nom.

Maintenant considérez:

  • Comparé aux humains, les machines sont vraiment bonnes pour la recherche et le tri
  • Comparé aux machines, les humains sont vraiment bons en matière d'invention et d'innovation

Donc, la réponse courte est: le virtual est une instruction de liaison tardive pour la machine (runtime) tandis que le abstract est l'instruction de liaison tardive pour l'humain (programmeur)

En d'autres termes, virtual signifie:

"Cher runtime , attachez le code approprié à ce nom en faisant ce que vous faites le mieux: chercher "

Alors que abstract signifie:

"Cher programmeur , veuillez lier le code approprié à ce nom en faisant ce que vous faites de mieux: inventer "

Par souci d'exhaustivité, la surcharge signifie:

"Cher compilateur , attachez le code approprié à ce nom en faisant ce que vous faites de mieux: le tri ".


  1. Seules abstract classes abstract peuvent avoir abstract membres abstract .
  2. Une classe non abstract qui hérite d'une classe abstract doit override ses membres abstract .
  3. Un membre abstract est implicitement virtual .
  4. Un membre abstract ne peut fournir aucune implémentation (le abstract est appelé pure virtual dans certaines langues).

Méthode virtuelle

  • Virtual signifie que nous pouvons le remplacer.

  • La fonction virtuelle a une implémentation. Lorsque nous héritons de la classe, nous pouvons remplacer la fonction virtuelle et fournir notre propre logique.

  • Nous pouvons changer le type de retour de la fonction virtuelle lors de la mise en
    fonction dans la classe des enfants (ce qui peut être dit comme un concept de
    Ombrage).

Méthode abstraite

  • Résumé signifie que nous devons l'ignorer.

  • Une fonction abstraite n'a pas d'implémentation et doit être dans une classe abstraite.

  • Cela peut seulement être déclaré. Cela force la classe dérivée à fournir l'implémentation de celle-ci.

  • Un membre abstrait est implicitement virtuel. Le résumé peut être appelé comme virtuel pur dans certaines langues.

    public abstract class BaseClass
    { 
        protected abstract void xAbstractMethod();
    
        public virtual void xVirtualMethod()
        {
            var x = 3 + 4;
        }
    } 
    

Vous devez toujours remplacer une fonction abstraite.

Ainsi:

  • Fonctions abstraites - quand l'héritier doit fournir sa propre implémentation
  • Virtuel - quand il appartient à l'héritier de décider

À ma compréhension:

Méthodes abstraites

Seule la classe abstraite peut contenir des méthodes abstraites. La classe dérivée doit également implémenter la méthode et aucune implémentation n'est fournie dans la classe.

Méthodes virtuelles

Une classe peut les déclarer et en fournir l'implémentation. De plus, la classe dérivée doit implémenter la méthode pour la surcharger.


Une fonction abstraite n'a pas d'implémentation et elle ne peut être déclarée que sur une classe abstraite. Cela force la classe dérivée à fournir une implémentation. Une fonction virtuelle fournit une implémentation par défaut et peut exister sur une classe abstraite ou une classe non abstraite. Donc par exemple:

public abstract class myBase
{
    //If you derive from this class you must implement this method. notice we have no method body here either
    public abstract void YouMustImplement();

    //If you derive from this class you can change the behavior but are not required to
    public virtual void YouCanOverride()
    { 
    }
}

public class MyBase
{
   //This will not compile because you cannot have an abstract method in a non-abstract class
    public abstract void YouMustImplement();
}

Méthode abstraite: Lorsqu'une classe contient une méthode abstraite, cette classe doit être déclarée comme abstraite. La méthode abstraite n'a pas d'implémentation et donc, les classes qui dérivent de cette classe abstraite, doivent fournir une implémentation pour cette méthode abstraite.

Méthode virtuelle: une classe peut avoir une méthode virtuelle. La méthode virtuelle a une implémentation. Lorsque vous héritez d'une classe qui a une méthode virtuelle, vous pouvez remplacer la méthode virtuelle et fournir une logique supplémentaire, ou remplacer la logique par votre propre implémentation.

Quand utiliser quoi? Dans certains cas, vous savez que certains types devraient avoir une méthode spécifique, mais vous ne savez pas quelle implémentation cette méthode devrait avoir.
Dans ce cas, vous pouvez créer une interface contenant une méthode avec cette signature. Cependant, si vous avez un tel cas, mais vous savez que les implémenteurs de cette interface auront également une autre méthode commune (pour laquelle vous pouvez déjà fournir l'implémentation), vous pouvez créer une classe abstraite. Cette classe abstraite contient alors la méthode abstraite (qui doit être surchargée), et une autre méthode qui contient la logique «commune».

Une méthode virtuelle devrait être utilisée si vous avez une classe qui peut être utilisée directement, mais pour laquelle vous voulez que les héritiers puissent changer certains comportements, bien que ce ne soit pas obligatoire.


Arriver en retard à la fête: j'utilise les types CLR 100% du temps (enfin, sauf si je suis obligé d'utiliser le type C #, mais je ne me souviens pas de la date de la dernière fois).

J'ai commencé à faire cela il y a des années, selon les livres CLR de Ritchie. Il était logique pour moi que tous les langages CLR doivent en fin de compte pouvoir prendre en charge l'ensemble des types de CLR. Par conséquent, l'utilisation des types de CLR vous-même fournit un code plus clair et éventuellement plus "réutilisable".

Maintenant que je le fais depuis des années, c'est une habitude et j'aime la coloration que VS montre pour les types CLR.

Le seul inconvénient réel est que l'auto-complétion utilise le type C #. Je finis donc par ressaisir les types générés automatiquement pour spécifier le type CLR.

De plus, maintenant, quand je vois "int" ou "string", cela me semble vraiment faux, comme si je regardais le code C des années 1970.







c# oop programming-languages virtual abstract