Что такое виртуальные методы? - PullRequest
64 голосов
/ 07 марта 2009

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

Какая выгода от использования виртуальной?

Ответы [ 15 ]

47 голосов
/ 07 марта 2009

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

Пример:

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()
}
41 голосов
/ 03 октября 2009

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

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

19 голосов
/ 07 марта 2009

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

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

13 голосов
/ 07 марта 2009

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

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

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

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

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

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

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

  • Ошибка использовать виртуальный модификатор для статического свойства.
  • Виртуальное наследуемое свойство может быть переопределено в производном классе включая декларацию о использует модификатор переопределения.
6 голосов
/ 07 марта 2009

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

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

5 голосов
/ 07 марта 2009

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

3 голосов
/ 31 декабря 2012

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

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

3 голосов
/ 07 марта 2009

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

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

1 голос
/ 23 мая 2017

Время выполнения происходит во время компиляции.
Когда вы объявляете метод как виртуальный, для объявления его в производном классе необходимо добавить модификатор override или new.
мы можем видеть это, когда TrySpeak. Передавая ребенка и отца, оба вызывают Speak of Father, в то время как TryScream будет вызывать каждый метод.
Чтобы понять это, есть некоторые вещи, которые мы должны знать, в случае с Child, есть два Scream метода из класса Child или класса Father. Мы могли бы либо позвонить в Scream из класса Child, либо из класса Father. Поскольку 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();
    }
}
1 голос
/ 26 января 2017

Здесь это ясно объясняется на примере C # Виртуальный метод

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