Utilisation de fonctions virtuelles en c#

Quelle est l'utilisation de fonctions virtuelles en c#?

45
demandé sur odiseh 2009-06-30 10:54:35

9 réponses

Donc en gros si dans votre classe ancêtre vous voulez un certain comportement d'une méthode. Si votre descendant utilise la même méthode mais a une implémentation différente, vous pouvez remplacer il, Si elle a un virtual mot clé.

using System;
class TestClass 
{
   public class Dimensions 
   {
      public const double pi = Math.PI;
      protected double x, y;
      public Dimensions() 
      {
      }
      public Dimensions (double x, double y) 
      {
         this.x = x;
         this.y = y;
      }

      public virtual double Area() 
      {
         return x*y;
      }
   }

   public class Circle: Dimensions 
   {
      public Circle(double r): base(r, 0) 
      {
      }

      public override double Area() 
      { 
         return pi * x * x; 
      }
   }

   class Sphere: Dimensions 
   {
      public Sphere(double r): base(r, 0) 
      {
      }

      public override double Area()
      {
         return 4 * pi * x * x; 
      }
   }

   class Cylinder: Dimensions 
   {
      public Cylinder(double r, double h): base(r, h) 
      {
      }

      public override double Area() 
      {
         return 2*pi*x*x + 2*pi*x*y; 
      }
   }

   public static void Main()  
   {
      double r = 3.0, h = 5.0;
      Dimensions c = new Circle(r);
      Dimensions s = new Sphere(r);
      Dimensions l = new Cylinder(r, h);
      // Display results:
      Console.WriteLine("Area of Circle   = {0:F2}", c.Area());
      Console.WriteLine("Area of Sphere   = {0:F2}", s.Area());
      Console.WriteLine("Area of Cylinder = {0:F2}", l.Area());
   }
}

Edit: Questions en commentaire

si je n'utilise pas le mot-clé virtuel dans la classe de base, est-ce que ça marchera?

Si vous utilisez le override mot-clé dans vos classes descendantes it ne fonctionnera pas. Vous générerez une erreur de compilation CS0506 'function1': ne peut pas outrepasser le membre hérité 'function2' parce qu'il n'est pas marqué "virtual", "abstract", ou "override"

Si vous n'utilisez pas le remplacer, Vous aurez l' CS0108 avertissement ' desc.Méthode()' cache la base de membre hérité'.Méthode()' Utiliser le nouveau mot-clé si cachette était prévu.

Pour contourner ce mettre le new mot-clé devant la méthode que vous êtes se cacher.

e.g.

  new public double Area() 
  {
     return 2*pi*x*x + 2*pi*x*y; 
  }

..et est-il obligatoire de remplacer une méthode virtuelle dans la classe dérivée?

Non, si vous n'outrepassez pas la méthode, la classe descendante utilisera la méthode dont elle hérite.

74
répondu Johnno Nolan 2010-08-20 12:11:27

la clé pour comprendre l'usage pratique des fonctions virtuelles est de garder à l'esprit qu'un objet d'une certaine classe peut être assigné à un autre objet d'une classe dérivé de la classe du premier objet.

par exemple:

class Animal {
   public void eat() {...}
}

class FlyingAnimal : Animal {
   public void eat() {...}
}

Animal a = new FlyingAnimal();

Animal classe a une fonction eat() cela décrit généralement comment un animal doit manger (par exemple, mettre l'objet dans la bouche et avaler).

cependant, le FlyingAnimal classe doit définir un nouveau eat() méthode, parce que les animaux volants ont une façon particulière de manger.

donc la question qui vient à l'esprit ici est: après que j'ai déclaré la variable a de type Animal et signé un nouvel objet de type FlyingAnimal, ce qui va a.eat() faire? Laquelle des deux méthodes est appelée?

la réponse ici est: parce que a est de type Animal, il va appeler Animal'méthode. Le compilateur est stupide et ne sait pas que vous allez assigner un objet d'une autre classe à a variable.

c'est Ici virtual mot clé vient en action: si vous déclarez la méthode virtual void eat() {...}, vous dites en gros au compilateur"faites attention que je fasse des choses intelligentes ici que vous ne pouvez pas gérer parce que vous n'êtes pas aussi intelligent". Ainsi le compilateur ne tentera pas de lier l'appel a.eat() à l'une ou l'autre des deux méthodes, mais à la place il dit au système de le faire lors de l'exécution!

Donc seulement lorsque le code s'exécute, le système recherche atype de contenu pas à son type déclaré et exécute FlyingAnimal'méthode.

vous pouvez Vous demander: pourquoi diable voudrais-je faire? Pourquoi ne pas le dire dès le début FlyingAnimal a = new FlyingAnimal()?

la raison en est que, par exemple, vous pouvez avoir beaucoup de classes dérivées de Animal:FlyingAnimal,SwimmingAnimal,BigAnimal,WhiteDog etc. Et à un moment donné vous voulez définir un monde contenant beaucoup Animals, de sorte que vous vous dites:

Animal[] happy_friends = new Animal[100];

nous avons un monde avec 100 animaux heureux. Vous les initialiser à un certain point:

...
happy_friends[2] = new AngryFish();
...
happy_friends[10] = new LoudSnake();
...

Et à la fin de la journée, vous voulez tout le monde à manger avant d'aller dormir. Donc, vous voulez dire:

for (int i=0; i<100; i++) {
   happy_friends[i].eat();
}

comme vous pouvez le voir, chaque animal a sa propre méthode de manger. Uniquement à l'aide de virtuel fonctions pouvez-vous atteindre cette fonctionnalité. Sinon, tout le monde serait forcé de "manger" exactement de la même manière: comme décrit dans le plus général eat fonction à l'intérieur de la Animal classe.

modifier: Ce comportement est en fait par défaut dans des langages communs de haut niveau comme Java.

58
répondu Bogdan Alexandru 2016-09-21 15:26:00

comme n'importe quelle autre langue..lorsque vous voulez polymorphisme. Il y a des tonnes d'utilisation de ce. Par exemple, vous voulez abstrait de la voie d'entrée est lu à partir d'une console ou d'un fichier ou d'un autre dispositif. Vous pouvez avoir une interface de lecteur Générique suivie de multiples implémentations concrètes en utilisant des fonctions virtuelles.

7
répondu Naveen 2009-06-30 06:58:11

par exemple les méthodes de proxy. c.-à-d. les méthodes d'écrasement à l'exécution. Par exemple, NHibernate utilise ceci pour supporter le chargement paresseux.

4
répondu Joachim Kerschbaumer 2009-06-30 06:58:23

fondamentalement les membres virtuels vous permettent d'exprimer le polymorphisme, une classe dérivée peut avoir une méthode avec la même signature que la méthode dans sa classe de base, et la classe de base appellera la méthode de la classe dérivée.

Un exemple de base:

public class Shape
{
    // A few example members
    public int X { get; private set; }
    public int Y { get; private set; }
    public int Height { get; set; }
    public int Width { get; set; }

    // Virtual method
    public virtual void Draw()
    {
        Console.WriteLine("Performing base class drawing tasks");
    }
}

class Circle : Shape
{
    public override void Draw()
    {
        // Code to draw a circle...
        Console.WriteLine("Drawing a circle");
        base.Draw();
    }
}
class Rectangle : Shape
{
    public override void Draw()
    {
        // Code to draw a rectangle...
        Console.WriteLine("Drawing a rectangle");
        base.Draw();
    }
}
class Triangle : Shape
{
    public override void Draw()
    {
        // Code to draw a triangle...
        Console.WriteLine("Drawing a triangle");
        base.Draw();
    }
}
3
répondu CMS 2009-06-30 07:00:14

cela permet d'obtenir une liaison tardive, c'est-à-dire de déterminer à l'exécution plutôt qu'à la compilation quel membre de l'objet sera invoqué. Voir Wikipédia.

3
répondu Juri 2009-06-30 09:17:34

ici:

dans la programmation orientée objet, un fonction virtuelle ou méthode virtuelle est une fonction ou une méthode dont le comportement peut être annulé dans un héritage classe par une fonction avec le même signature.

1
répondu Burkhard 2009-06-30 06:57:57

Par exemple, vous avez une classe de base Params et un ensemble de classes dérivées. Vous voulez pouvoir effectuer la même opération sur un tableau qui stocke toutes les classes possibles dérivées de params.

pas de problème - déclarez la méthode virtuelle, ajoutez une implémentation de base à la classe Params et outrepassez-la dans les classes dérivées. Maintenant vous pouvez simplement traverser le tableau et appeler la méthode par la référence - la méthode correcte sera appelée.

class Params {
public:
   virtual void Manipulate() { //basic impl here }
}

class DerivedParams1 : public Params {
public:
   override void Manipulate() {
      base.Manipulate();
      // other statements here
   }
};

// more derived classes can do the same

void ManipulateAll( Params[] params )
{
    for( int i = 0; i < params.Length; i++ ) {
       params[i].Manipulate();
    }
 }
1
répondu sharptooth 2009-06-30 06:58:37

utilisation de fonctions virtuelles en c#

les fonctions virtuelles sont principalement utilisées pour outrepasser la méthode de la classe de base dans la classe dérivée avec la même signature.

Quand une classe dérivée hérite de la classe de base, l'objet de la classe dérivée est une référence à la dérivée de la classe ou de la classe de base.

les fonctions virtuelles sont résolues tardivement par le compilateur(I. e fixation du temps d'exécution)

virtual dans la classe de base, les classes les plus dérivées la mise en œuvre de la fonction est appelée, selon le type réel de l'objet visé, quel que soit le type déclaré de l'pointeur ou d'une référence. Si elle n'est pas virtual, la méthode est résolu early et la fonction appelée est sélectionné en fonction du type déclaré de l'pointeur ou d'une référence.

1
répondu Divya 2013-10-07 18:39:51