virtuelle - virtual c#




Quelle est la différence entre une fonction abstraite et une fonction virtuelle? (14)

  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).

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?


À 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.


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.


Fonction abstraite:

  1. Il ne peut être déclaré qu'à l'intérieur d'une classe abstraite.
  2. Il contient uniquement la déclaration de méthode et non l'implémentation dans la classe abstraite.
  3. Il doit être remplacé dans la classe dérivée.

Fonction virtuelle

  1. Il peut être déclaré dans une classe abstraite ou non-abstraite.
  2. Il contient l'implémentation de la méthode.
  3. Cela peut être annulé.

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();
    }
}

Je l'ai simplifié en apportant quelques améliorations sur les 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(string[] 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 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.


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.


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();
}

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 doit être implémentée dans une classe concrète.

Une méthode virtuelle est une méthode qui peut être surchargée dans une classe dérivée en utilisant le remplacement, en remplaçant le comportement dans la superclasse. Si vous ne surchargez pas, vous obtenez le comportement original. Si vous le faites, vous obtenez toujours le nouveau comportement. Cela s'oppose aux méthodes non virtuelles, qui ne peuvent pas être remplacées mais qui peuvent masquer la méthode d'origine. 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");
    }
}

Quand DerivedClass et appelle SayHello , ou SayGoodbye , je reçois "Hi There" et "A plus tard". Si j'appelle HelloGoodbye , je reçois "Bonjour" et "A plus tard". C'est parce que SayGoodbye est virtuel, et peut être remplacé par des classes dérivées. SayHello est seulement caché, donc quand j'appelle ça de ma classe de base, j'obtiens ma méthode originale.

Les méthodes abstraites sont implicitement virtuelles. Ils définissent un comportement qui doit être présent, plus comme une interface.


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)


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?


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 ".


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;
        }
    } 
    




abstract