Практическое использование виртуальных функций в c#

Переменные являются глобальными, если не объявлены как локальные !!

Плохо (DoSomething () вызывается только 10 раз):

function CountToTen()
{
  for(i=0; i< 10; i++)
  {
    DoSomething(i);
  }
}

function countToFive()
{
  for(i=0; i<5; i++)
  {
    CountToTen();
  }
}

CountToFive();

Хорошо (DoSomething ( ) вызывается 50 раз, как и предполагалось):

function CountToTen()
{
  var i;
  for(i=0; i< 10; i++)
  {
    DoSomething(i);
  }
}

function countToFive()
{
  var i;
  for(i=0; i<5; i++)
  {
    CountToTen();
  }
}

CountToFive();
49
задан odiseh 29 June 2009 в 19:54
поделиться

7 ответов

Итак, в основном, если в вашем классе-предке вам нужно определенное поведение для метода. Если ваш потомок использует тот же метод, но имеет другую реализацию, вы можете переопределить его, если у него есть ключевое слово virtual .

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

Изменить: Вопросы в комментарии
Если я не использую ключевое слово virtual в базовом классе, будет ли оно работать?

Если вы используете ключевое слово override в своих дочерних классах, оно не будет работать. Вы получите ошибку компилятора CS0506 'function1':

82
ответ дан 7 November 2019 в 11:15
поделиться

Как любой другой язык ... когда вам нужен полиморфизм. Для этого есть множество способов использования. Например, вы хотите абстрагироваться от способа чтения ввода с консоли, файла или другого устройства. У вас может быть общий интерфейс читателя, за которым следуют несколько конкретных реализаций с использованием виртуальных функций.

7
ответ дан 7 November 2019 в 11:15
поделиться

например, методы прокси. т.е. методы перезаписи во время выполнения. Например, NHibernate использует это для поддержки отложенной загрузки.

4
ответ дан 7 November 2019 в 11:15
поделиться

В основном виртуальные члены позволяют выражать полиморфизм, производный класс может иметь метод с той же сигнатурой, что и метод в его базовом классе, и базовый класс вызовет метод производного класса.

Базовый пример:

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
ответ дан 7 November 2019 в 11:15
поделиться

Это позволяет достичь позднего связывания, то есть определять во время выполнения, а не во время компиляции, какой член объекта будет вызван. См. Википедию .

4
ответ дан 7 November 2019 в 11:15
поделиться

Из здесь :

В объектно-ориентированном программировании виртуальная функция или виртуальный метод функция или метод, поведение которых можно переопределить в наследуемом класс функцией с таким же подпись.

1
ответ дан 7 November 2019 в 11:15
поделиться

Например, у вас есть базовый класс Params и набор производных классов. Вы хотите иметь возможность выполнять ту же операцию с массивом, в котором хранятся все возможные классы, производные от params.

Нет проблем - объявите метод виртуальным, добавьте базовую реализацию в класс Params и переопределите ее в производных классах. Теперь вы можете просто пройти по массиву и вызвать метод по ссылке - будет вызван правильный метод.

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
ответ дан 7 November 2019 в 11:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: