Что такое виртуальные методы?

Почему вы объявляете метод как "виртуальный".

В чем выгода от использования виртуальной?

15 ответов

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

Пример:

class A
{
    public virtual void Foo()
       //DoStuff For A
}

class B : A
{
    public override void Foo()
    //DoStuff For B

    //now call the base to do the stuff for A and B 
    //if required
    base.Foo()
}

Virtual позволяет наследующему классу заменить метод, который затем использует базовый класс.

public class Thingy
{
    public virtual void StepA()
    {
        Console.Out.WriteLine("Zing");
    }

    public void Action()
    {
        StepA();
        Console.Out.WriteLine("A Thingy in Action.");
    }
}

public class Widget : Thingy
{
    public override void StepA()
    {
        Console.Out.WriteLine("Wiggy");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Thingy thingy = new Thingy();
        Widget widget = new Widget();

        thingy.Action();
        widget.Action();

        Console.Out.WriteLine("Press any key to quit.");
        Console.ReadKey();
    }
 }

Когда вы запустите Программу, ваш вывод будет:

Zing 
A Thingy in Action. 
Wiggy 
A Thingy in Action.

Обратите внимание, что, хотя Widget и вызывал метод Action(), определенный на уровне Thingy, внутренне Thingy вызывал метод Widget StepA().

Основной ответ - это дает наследникам класса больше гибкости. Конечно, вы должны хорошо спроектировать свой класс, иначе это может привести к хаосу.

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

Не виртуальный метод - это тип метода, где фактический вызываемый метод зависит от ссылочного типа объекта в точке вызова метода.

Виртуальные методы на MSDN

Ключевое слово virtual используется для изменения объявления метода или свойства, и в этом случае метод или свойство называется виртуальным членом. Реализация виртуального члена может быть изменена переопределяющим членом в производном классе.

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

По умолчанию методы не виртуальные. Вы не можете переопределить не виртуальный метод.

Вы не можете использовать виртуальный модификатор со следующими модификаторами:

статическое абстрактное переопределение

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

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

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

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

Я использую RhinoMocks, у которого есть это ограничение, и по этой причине по умолчанию пометил мои методы виртуальными. Для меня это, вероятно, самая главная причина использования виртуальных методов, поскольку случаи, когда наследование вступает в игру, встречаются гораздо реже.

Короткий вопрос, короткий ответ! Определите ваш метод как "виртуальный", если вы думаете, что унаследуете класс, которому он принадлежит.

Более длинный ответ: "Виртуальный позволяет вам переопределить, чтобы дать другое значение вашего метода в производном классе.

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

Проверьте запись MSDN для ключевого слова. Это объясняет это более подробно.

Время выполнения происходит во время компиляции.
Когда вы объявляете метод как виртуальный, для объявления его в производном классе необходимо добавить override или же new модификатор.
мы можем видеть, что когда TrySpeak, Проходя через ребенка и отца, оба зовут говорить об отце, а TryScream, будет вызывать каждый метод.
Чтобы понять это, есть некоторые вещи, которые мы должны знать, в случае с Child, есть два Scream методы из дочернего класса или класса отца. Мы могли бы либо позвонить Scream из детского класса или отцовского класса. Так как Virtaul Модификатор помечает метод так, что он может быть переопределен производным классом, что означает, что даже Scream вызывается из класса Father, он переопределяется, он будет защищен, если вы используете новый модификатор.

import system;
class Father
{
    Speak()
    {
        Console.Writeline("Father is speaking") 
    }
    virtual Scream()
    {
        Console.Writeline("Father is screaming")    
    }
}
class Child: father
{
    Speak()
    {
        Console.Writeline("Child is speaking")  
    }
    override Scream()
    {
        Console.Writeline("Child is screaming") 
    }
}
class APP
{
    public static void Main()
    {
        // We new two instances here
        Father father = new Father();
        Child child = new Child();        
        // Here we call their scream or speak through TryScream or TrySpeak
        TrySpeak(father);
        TrySpeak(child);
        //>>>"Father is speaking"
        //>>>"Father is speaking"
        TryScream(father);
        TryScream(child);
        //>>>"Father is screaming"
        //>>>"Child is screaming"
    }
    // when your method take an Parameter who type is Father
    // You can either pass in a Father instance or
    // A instance of a derived Class from Father
    // which could be Child
    public static void TrySpeak(Father person)
    {
        person.Scream();
    }
    public static void TryScream(Father person)
    {
        person.Speak();
    }
}

В C# для переопределения метода базового класса в производном классе вы должны объявить метод базового класса как метод виртуального и производного класса как переопределение, как показано ниже:

using System;
namespace Polymorphism
{
 class A
 {
 public virtual void Test() { Console.WriteLine("A::Test()"); }
 }

 class B : A
 {
 public override void Test() { Console.WriteLine("B::Test()"); }
 }

 class C : B
 {
 public override void Test() { Console.WriteLine("C::Test()"); }
 }

 class Program
 {
 static void Main(string[] args)
 {

 A a = new A();
 B b = new B();
 C c = new C();
 a.Test(); // output --> "A::Test()"
 b.Test(); // output --> "B::Test()"
 c.Test(); // output --> "C::Test()"

 a = new B();
 a.Test(); // output --> "B::Test()"

 b = new C();
 b.Test(); // output --> "C::Test()"

 Console.ReadKey();
 }
 }
}

Вы также можете смешать скрытие метода и переопределение метода, используя ключевое слово virtual и new, поскольку метод производного класса может быть виртуальным и новым одновременно. Это необходимо, когда вы хотите переопределить метод производного класса на следующем уровне, так как я переопределяю метод класса B, Test() в классе C, как показано ниже:

using System;
namespace Polymorphism
{
 class A
 {
 public void Test() { Console.WriteLine("A::Test()"); }
 }

 class B : A
 {
 public new virtual void Test() { Console.WriteLine("B::Test()"); }
 }

 class C : B
 {
 public override void Test() { Console.WriteLine("C::Test()"); }
 }

 class Program
 {
 static void Main(string[] args)
 {

 A a = new A();
 B b = new B();
 C c = new C();

 a.Test(); // output --> "A::Test()"
 b.Test(); // output --> "B::Test()"
 c.Test(); // output --> "C::Test()"

 a = new B();
 a.Test(); // output --> "A::Test()"

 b = new C();
 b.Test(); // output --> "C::Test()"

 Console.ReadKey();
 }
 }
}

ЗОЛОТЫЕ СЛОВА: виртуальное ключевое слово используется для изменения метода, свойства, индексатора или события, объявленного в базовом классе, и позволяет переопределить его в производном классе.

Ключевое слово override используется для расширения или изменения виртуального / абстрактного метода, свойства, индексатора или события базового класса в производный класс.

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

НАСЛАЖДАТЬСЯ:-)

Эта ссылка предоставит вам лучшее понимание с очень простым примером /questions/33896235/zachem-nam-nuzhnyi-virtualnyie-funktsii-v-c/33896248#33896248

Здесь это ясно объясняется на примере C# Virtual Method

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

    public class sample {
      public virtual void fun(){
        Console.WriteLine("base sample class \n");
      }
    }
    public class A : sample{
      public override void fun(){
        Console.WriteLine("Class A \n");
      }
    }
    public class B : sample{
      public override void fun(){
        Console.WriteLine("Class B \n");
      }
    }
    class run{
      public static void main(String[] args){
        sample obj = new sample();
        sample obj1 = new A();
        sample obj2 = new B();
        obj.fun();
        obj1.fun();
        obj2.fun();
      }
    }

Излишне говорить, что виртуальные методы пригодятся, когда ваш код пытается придерживаться принципа Open Closed

Узнайте больше об Открытом закрытом принципе здесь, оригинальном официальном документе OCP дяди Боба.

Также, пожалуйста, имейте в виду, что методы не являются виртуальными по умолчанию в C# в отличие от Java.

Разница между виртуальными и не виртуальными методами.

У нас есть два класса; один - это класс Vehicle, а другой - класс Cart. Класс "Автомобиль" - это базовый класс, который имеет два метода; один - это виртуальный метод "Speed ​​()", а другой - не виртуальный метод "Average()". Поэтому виртуальный метод базового класса "Speed ​​()" переопределяется в подклассе. У нас есть еще один класс "Программа" (класс исполнения), у которого есть точка входа, где мы создаем экземпляр подкласса "Корзина", и этот экземпляр присваивается типу базового класса "Автомобиль". Когда мы вызываем виртуальные и не виртуальные методы экземпляром обоих классов, то в соответствии с типом запуска вызывается реализация виртуального метода экземпляра; другими словами, оба экземпляра класса вызывают метод переопределения подкласса, а вызываемый не виртуальный метод определяется на основе экземпляра класса.

using System;

namespace VirtualExample
{   
    class Vehicle
    {   
       public double distance=0.0;
       public double hour =0.0;
       public double fuel =0.0; 

       public Vehicle(double distance, double hour, double fuel)
       {
           this.distance = distance;
           this.hour = hour;
           this.fuel = fuel;
       }

       public void Average()
       {
           double average = 0.0;
           average = distance / fuel;
           Console.WriteLine("Vehicle Average is {0:0.00}", average);
       }

       public virtual void Speed()
       {
           double speed = 0.0;
           speed = distance / hour;
           Console.WriteLine("Vehicle Speed is {0:0.00}", speed);
       }
    } 

    class Car : Vehicle
    {
        public Car(double distance, double hour, double fuel)
            : base(distance, hour, fuel)
        {
        }
      public void Average()
        {
            double average = 0.0;
            average = distance / fuel;
            Console.WriteLine("Car Average is {0:0.00}", average);
        }

        public override void Speed()
        {
            double speed = 0.0;           
            speed = distance / hour;
            Console.WriteLine("Car Speed is {0:0.00}", speed);
        }
    } 

    class Program
   {
        static void Main(string[] args)
        {
             double distance,hour,fuel=0.0;
             Console.WriteLine("Enter the Distance");
             distance = Double.Parse(Console.ReadLine());
             Console.WriteLine("Enter the Hours");
             hour = Double.Parse(Console.ReadLine());
             Console.WriteLine("Enter the Fuel");
             fuel = Double.Parse(Console.ReadLine());
             Car objCar = new Car(distance,hour,fuel);
             Vehicle objVeh = objCar;
             objCar.Average();
             objVeh.Average();
             objCar.Speed();
             objVeh.Speed();
            Console.Read();
        }       
    }
}

надеюсь помочь!

Другие вопросы по тегам