Quelle est la différence entre une fonction abstraite et une fonction virtuelle? Dans quels cas est-il recommandé d’utiliser virtual ou abstract? Quelle est l’approche la plus correcte?
Une fonction abstraite ne peut pas avoir de fonctionnalité. En gros, vous dites que toute classe enfant DOIT donner sa propre version de cette méthode, mais il est trop général d’essayer même de l’implémenter dans la classe parente.
Une fonction virtuelle , en gros, dit regarder, voici la fonctionnalité qui peut ou peut ne pas être assez bonne pour la classe enfant. Donc, si c’est assez bon, utilisez cette méthode, sinon, remplacez-moi et fournissez vos propres fonctionnalités.
Une fonction abstraite n’a pas d’implémentation et 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 soit sur une classe abstraite, soit sur 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 comstack because you cannot have an abstract method in a non-abstract class public abstract void YouMustImplement(); }
abstract
classes abstract
peuvent avoir abstract
membres abstract
. abstract
qui hérite d’une classe abstract
doit override
ses membres abstract
. abstract
est implicitement virtual
. abstract
ne peut fournir aucune implémentation ( abstract
est appelé pure virtual
dans certaines langues). Vous devez toujours remplacer une fonction abstraite.
Ainsi:
Fonction abstraite:
Fonction virtuelle:
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, par conséquent, les classes dérivées 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 dotée d’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 doivent avoir une méthode spécifique, mais vous ne savez pas quelle implémentation cette méthode doit 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 que 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 remplacée) et une autre méthode contenant 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 souhaitez que les héritiers puissent modifier certains comportements, bien que cela ne soit pas obligatoire.
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 au sujet du feu. De temps en temps, quelque part dans le monde, un feu brûle un gratte-ciel. Mais heureusement, nous avons ici un manuel d’instructions sur ce qu’il faut faire en cas d’incendie:
Escalier de secours()
Ceci est fondamentalement une méthode virtuelle appelée FireEscape ()
Méthode virtuelle
Ce plan est assez bon pour 99% des circonstances. C’est un plan de base qui fonctionne. Mais il y a 1% de chances que la sortie 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 par votre propre version du plan:
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 des exercices d’incendie. Ils n’ont pas de politique d’évasion globale. Chaque homme est pour lui-même. La direction ne s’intéresse qu’à une telle politique existante.
En d’autres termes, chaque personne est obligée de développer sa propre méthode FireEscape (). Un gars sortira de la sortie de secours. Un autre gars va parachuter. Un autre gars utilisera la technologie de propulsion des fusées pour s’envoler du bâtiment. Un autre gars sortira en rappel. La direction ne se soucie pas de la façon dont vous vous échappez, tant que vous avez un plan FireEscape () de base. C’est ce que l’on entend par une méthode abstraite.
Quelle est la différence entre les deux encore?
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.
Maintenant, ce n’était pas si difficile?
Une méthode abstraite est une méthode qui doit être implémentée pour créer une classe concrète. La déclaration est dans la classe abstraite (et toute classe avec une méthode abstraite doit être une classe abstraite) et elle doit être implémentée dans une classe concrète.
Une méthode virtuelle est une méthode qui peut être remplacée dans une classe dérivée à l’aide du remplacement, en remplaçant le comportement dans la superclasse. Si vous ne remplacez pas, vous obtenez le comportement d’origine. Si vous le faites, vous obtenez toujours le nouveau comportement. Ceci s’oppose aux méthodes non virtuelles, qui ne peuvent pas être remplacées mais peuvent masquer la méthode originale. Ceci est fait en utilisant le new
modificateur.
Voir l’exemple suivant:
public class BaseClass { public void SayHello() { Console.WriteLine("Hello"); } public virtual void SayGoodbye() { Console.WriteLine("Goodbye"); } public void HelloGoodbye() { this.SayHello(); this.SayGoodbye(); } } public class DerivedClass : BaseClass { public new void SayHello() { Console.WriteLine("Hi There"); } public override void SayGoodbye() { Console.WriteLine("See you later"); } }
Lorsque DerivedClass
et que j’appelle SayHello
ou SayGoodbye
, je reçois “Hi There” et “See you later”. Si j’appelle HelloGoodbye
, j’obtiens “Bonjour” et “À plus tard”. C’est parce que SayGoodbye
est virtuel et peut être remplacé par des classes dérivées. SayHello
est seulement caché, alors quand je l’appelle de ma classe de base, je reçois ma méthode originale.
Les méthodes abstraites sont implicitement virtuelles. Ils définissent un comportement qui doit être présent, tout comme une interface.
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 en avez l’implémentation par défaut et souhaitez autoriser les descendants à modifier son comportement.
Avec une méthode abstraite, vous forcez les descendants à fournir une implémentation.
J’ai simplifié les choses en apportant quelques améliorations aux classes suivantes (à partir d’autres réponses):
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestOO { class Program { static void Main(ssortingng[] args) { BaseClass _base = new BaseClass(); Console.WriteLine("Calling virtual method directly"); _base.SayHello(); Console.WriteLine("Calling single method directly"); _base.SayGoodbye(); DerivedClass _derived = new DerivedClass(); Console.WriteLine("Calling new method from derived class"); _derived.SayHello(); Console.WriteLine("Calling overrided method from derived class"); _derived.SayGoodbye(); DerivedClass2 _derived2 = new DerivedClass2(); Console.WriteLine("Calling new method from derived2 class"); _derived2.SayHello(); Console.WriteLine("Calling overrided method from derived2 class"); _derived2.SayGoodbye(); Console.ReadLine(); } } public class BaseClass { public void SayHello() { Console.WriteLine("Hello\n"); } public virtual void SayGoodbye() { Console.WriteLine("Goodbye\n"); } public void HelloGoodbye() { this.SayHello(); this.SayGoodbye(); } } public abstract class AbstractClass { public void SayHello() { Console.WriteLine("Hello\n"); } //public virtual void SayGoodbye() //{ // Console.WriteLine("Goodbye\n"); //} public abstract void SayGoodbye(); } public class DerivedClass : BaseClass { public new void SayHello() { Console.WriteLine("Hi There"); } public override void SayGoodbye() { Console.WriteLine("See you later"); } } public class DerivedClass2 : AbstractClass { public new void SayHello() { Console.WriteLine("Hi There"); } // We should use the override keyword with abstract types //public new void SayGoodbye() //{ // Console.WriteLine("See you later2"); //} public override void SayGoodbye() { Console.WriteLine("See you later"); } } }
La liaison est le processus de mappage d’un nom à une unité de code.
La liaison tardive signifie que nous utilisons le nom, mais que nous reportons 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:
Donc, la réponse courte est: virtual
est une instruction de liaison tardive pour la machine (runtime) alors que abstract
est l’instruction de liaison tardive pour l’humain (programmeur)
En d’autres termes, virtual
signifie:
“Cher runtime , liez le code approprié à ce nom en faisant ce que vous faites le mieux: la recherche ”
Considérant que abstract
signifie:
“Cher programmeur , veuillez lier le code approprié à ce nom en faisant ce que vous faites le mieux: inventer ”
Par souci d’exhaustivité, la surcharge signifie:
“Cher compilateur , liez le code approprié à ce nom en faisant ce que vous faites le mieux: le sorting “.
Vous utilisez essentiellement une méthode virtuelle lorsque vous souhaitez que les héritiers étendent les fonctionnalités s’ils le souhaitent.
Vous utilisez des méthodes abstraites lorsque vous souhaitez que les héritiers implémentent la fonctionnalité (et dans ce cas, ils n’ont pas le choix)
J’ai vu dans certains endroits la méthode abstraite définie ci-dessous. **
“Une méthode abstraite doit être implémentée dans la classe enfant”
** Je sentais que c’était comme.
Il n’est pas nécessaire qu’une méthode abstraite soit implémentée dans une classe enfant, si la classe enfant est également abstraite .
1) Une méthode abstraite ne peut ê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é .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(); } }
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.
Méthode abstraite
Résumé signifie que nous devons le remplacer
Une fonction abstraite n’a pas d’implémentation et doit être dans une classe abstraite.
Il ne peut être déclaré que Cela force la classe dérivée à en fournir l’implémentation.
Un membre abstrait est implicitement virtuel. Le résumé peut être appelé purement virtuel dans certaines des langues.
public abstract class BaseClass { protected abstract void xAbstractMethod(); public virtual void xVirtualMethod() { var x = 3 + 4; } }
La fonction abstraite ne peut pas avoir de corps et DOIT être remplacée par les classes enfants
La fonction virtuelle aura un corps et pourra ou non être remplacé par des classes enfant
La plupart des exemples ci-dessus utilisent du code – et ils sont très très bons. Je n’ai pas besoin d’append à ce qu’ils disent, mais voici une explication simple qui utilise des analogies plutôt que des termes de code / techniques.
Explication simple – Explication en utilisant des analogies
Méthode abstraite
Pensez à George W. Bush. Il dit à ses soldats: “Allez vous battre en Irak”. Et c’est tout. Tout ce qu’il a spécifié, c’est que des combats doivent être faits. Il ne précise pas comment cela se passera exactement. Mais je veux dire, vous ne pouvez pas simplement sortir et “combattre”: 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 placé dans l’armée. Il a défini ce que signifie le combat:
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. Une bonne chose pour Petraeus est que ses commandes ont une marge de manœuvre et une scope – il a permis à d’autres de changer sa définition du terme “combat”, en fonction de leurs exigences particulières.
Private Job Bloggs lit la commande de Petraeus et est autorisé à mettre en œuvre sa propre version de combat, en fonction de ses exigences particulières:
Nouri al Maliki reçoit également les mêmes commandes de Petraeus. Il doit se battre aussi. Mais c’est un homme politique, pas un homme d’infanterie. De toute évidence, il ne peut pas tourner autour de ses ennemis politiques dans la tête. Comme Petraeus lui a donné une méthode virtuelle, Maliki peut alors implémenter sa propre version de la méthode de combat, en fonction de sa situation particuliè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 dans 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. Ceci doit être fourni par quelqu’un d’autre. C’est une méthode abstraite.
Petraeus, quant à lui, fournit des détails d’implémentation, mais il a donné la permission à ses subordonnés de passer outre ses ordres avec leur propre version, s’ils peuvent proposer 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 doit ê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 qui peut être remplacée par la méthode de la classe dérivée à l’aide du mot clé override.
● Il appartient à la classe dérivée de la remplacer ou non.
La réponse a été fournie un certain nombre de fois, mais la question de savoir quand utiliser chacune est une décision de conception. Je verrais comme une bonne pratique d’essayer de regrouper des définitions de méthodes communes en interfaces distinctes et de les classer dans des classes aux niveaux d’abstraction appropriés. L’extraction d’un ensemble commun de définitions de méthodes abstraites et virtuelles dans une classe rend la classe non stable lorsqu’il peut être 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 à vos besoins spécifiques.
De la vue générale orientée object:
Concernant la méthode abstraite : Lorsque vous placez 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!
Concernant la fonction virtuelle : Lorsque vous placez une méthode virtuelle dans la classe parente que vous dites aux classes dérivées: Hey, il existe une fonctionnalité qui fait quelque chose pour vous. Si cela vous est utile, utilisez-le simplement. Sinon, remplacez ceci et implémentez votre code, même vous pouvez utiliser mon implémentation dans votre code!
c’est une philosophie sur la différence entre ces deux concepts dans General OO
Il n’y a rien qui appelle la classe virtuelle en C #.
Pour les fonctions
Vous pouvez décider avec votre exigence.
La méthode abstraite n’a pas d’implémentation. Elle est déclarée dans la classe parente. La classe enfant est responsable de l’implémentation de cette méthode.
La méthode virtuelle doit avoir une implémentation dans la classe parente et faciliter la classe enfant à choisir d’utiliser cette implémentation de la classe parente ou de disposer d’une nouvelle implémentation pour cette méthode dans la classe enfant.
Une fonction abstraite est “juste” une signature, sans implémentation. Il est utilisé dans une interface pour déclarer comment la classe peut être utilisée. Il doit être implémenté dans l’une des classes dérivées.
La fonction virtuelle (méthode en fait) est une fonction que vous déclarez également et devrait être implémentée dans l’une des classes de la hiérarchie d’inheritance.
Les instances héritées d’une telle classe héritent également de l’implémentation, sauf si vous l’implémentez, dans une classe de hiérarchie inférieure.
À ma compréhension:
Méthodes abstraites:
Seule la classe abstraite peut contenir des méthodes abstraites. De plus, la classe dérivée doit 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 fournir la même implémentation. La classe dérivée doit également implémenter la méthode pour la remplacer.