переопределение функции c # - PullRequest
7 голосов
/ 29 ноября 2011

Я просто пытался освоить концепцию виртуальной функции с помощью консольного приложения.Я заметил, что как только я переопределяю функцию базового класса, return baseclassname.functionname (параметры) автоматически вставляется в мое тело функции.Почему это происходит?

class advanc
{
    public virtual int  calc (int a , int b)
    {        
         return (a * b);        
    }        
}

class advn : advanc
{
     public override int calc(int a, int b)
     {
          //automatically inserted
          return base.calc(a, b);
      }        
}

Ответы [ 7 ]

12 голосов
/ 29 ноября 2011

Переопределяя виртуальную функцию, вы расширяете функциональность вашего базового класса, а затем вызываете базовый класс для «базовой функциональности».

Если вы удалите строку 'return base.calc(a,b)', базовый класскод не будет выполняться.

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

Следующий код демонстрирует это (простоэто в консольном приложении)

class advanc
{
    public virtual int calc(int a, int b)
    {
        Console.WriteLine("Base function called");
        return (a * b);
    }
}

class advn : advanc
{
    public bool CallBase { get; set; }
    public override int calc(int a, int b)
    {
        Console.WriteLine("Override function called");

        if (CallBase)
        {
            return base.calc(a, b);
        }
        else
        {
            return a / b;
        }
    }
}

private static void Main()
{
    advn a = new advn();

    a.CallBase = true;
    int result = a.calc(10, 2);
    Console.WriteLine(result);

    a.CallBase = false;
    result = a.calc(10, 2);
    Console.WriteLine(result);
    Console.WriteLine("Ready");
    Console.ReadKey();
}
5 голосов
/ 29 ноября 2011

Visual Studio пытается угадать, что вы хотите, поэтому предлагает вам этот код.

Иногда переопределенные функции расширяют функциональность функций базового класса. В этом случае можно вызвать base.function где-то внутри переопределенного.

2 голосов
/ 29 ноября 2011

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

Кроме того, существуют некоторые сценарии, в которых вызов метода базового класса имеет смысл даже после вашей реализации:

  1. поведение вашего дочернего класса расширяется на основе, но не заменяет его полностью
  2. вы используете шаблон декоратора , но ваш метод calc не нуждается в изменении (вам все еще нужно его реализовать, потому что он является частью исходного интерфейса, который вы украшаете, но вы просто переадресация вызова в ваш базовый класс без изменения поведения)
2 голосов
/ 29 ноября 2011

Это означает, что когда он вызывает base.calc, он вызывает функцию родителей, которую он переопределяет. Если вы не хотите вызывать базовую функцию, вы можете удалить ее, но в большинстве случаев она останется (именно поэтому Visual Studio Auto генерирует ее).

Если в вашей расширенной функции вы не хотите вызывать функцию a * b, вы удалите вызов базовой функции и напишите свой собственный.

например. если вы объявите это в своем классе advn:

public override int calc(int a, int b)
{
   return Math.Pow(a, b);
}

При вызове этой функции вы получите следующее:

advanc myObj = new advanc();
advn advnObj = new advn();

myObj.calc(5, 2); // will return 10
advnObj.calc(5, 2); // will return 25
1 голос
/ 29 ноября 2011

Тело базовой функции вызывается автоматически из-за строки return base.calc(a, b); Но вы можете просто сделать так, чтобы тело базовой функции не вызывалось автоматически, а вызывать ваш объект следующим образом:

    class advn : advanc
    {
        public override int calc(int a, int b)
        {
             return a * b; //anything else;
        }

    }
1 голос
/ 29 ноября 2011

По умолчанию VS предлагает, по крайней мере, сделать то, что делает родитель в функции. Кроме того, во многих случаях вам нужно запустить parent, а затем выполнить свое действие (например, в случаях с пользовательским интерфейсом). для base см. MSDN об этом:

Ключевое слово base используется для доступа к членам базового класса из в производном классе:

Call a method on the base class that has been overridden by another method.
Specify which base-class constructor should be called when creating instances 
of the derived class.

Доступ к базовому классу разрешен только в конструкторе, экземпляре метод или метод доступа к экземпляру.

1 голос
/ 29 ноября 2011

IDE просто вставляет вызов в базовую реализацию. Это означает, что по умолчанию поведение переопределения будет идентичным методу переопределения. Если это нежелательное поведение (скорее всего, нет), просто измените код по вашему выбору.

...