[c#] Quelle est la différence entre une fonction abstraite et une fonction virtuelle?


9 Answers

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

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?




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.




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.




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



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



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ée par les classes enfants




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



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.




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.




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.






Related