Что такое Shadowing? - PullRequest
       54

Что такое Shadowing?

34 голосов
/ 23 марта 2009

В C # что означает термин shadowing ? Я прочитал эту ссылку , но не до конца ее понял.

Ответы [ 11 ]

45 голосов
/ 23 марта 2009

Shadowing скрывает метод в базовом классе. Используя пример в вопросе, который вы связали:

class A 
{
   public int Foo(){ return 5;}
   public virtual int Bar(){return 5;}
}
class B : A
{
   public new int Foo() { return 1;}
   public override int Bar() {return 1;}
}

Класс B переопределяет виртуальный метод Bar. Он скрывает (тени) не виртуального метода Foo. Переопределение использует ключевое слово override . Затенение выполняется с помощью ключевого слова new .

В приведенном выше коде, если вы не использовали ключевое слово new при определении метода Foo в классе B, вы получите предупреждение компилятора:

'test.B.Foo()' hides inherited member 'test.A.Foo()'. Use the new keyword if hiding was intended.
32 голосов
/ 23 марта 2009
  • Переопределение: переопределение существующего метода в базовом классе
  • Затенение: создание совершенно нового метода с той же сигнатурой, что и в базовом классе
20 голосов
/ 23 марта 2009

Предположим, у меня есть базовый класс, который реализует виртуальный метод:

public class A
{
    public virtual void M() { Console.WriteLine("In A.M()."); }
}

У меня также есть производный класс, который также определяет метод M:

public class B : A
{
    // could be either "new" or "override", "new" is default
    public void M() { Console.WriteLine("In B.M()."); }
}

Теперь предположим, что я пишу такую ​​программу:

A alpha = new B(); // it's really a B but I cast it to an A
alpha.M();

У меня есть два разных варианта того, как я хочу, чтобы это было реализовано. Поведение по умолчанию состоит в том, чтобы вызывать версию M. (это идентично поведению, если вы применили ключевое слово "new" к B.M().)

Это называется "теневым копированием", когда у нас есть метод с тем же именем, но другим поведением при вызове из базового класса.

С другой стороны, мы могли бы указать "override" на B.M(). В этом случае alpha.M() назвал бы версию Б М.

10 голосов
/ 23 марта 2009

Слежение заключается в сокрытии метода базового класса с новым определением в дочернем классе.

Разница между скрытием и переопределением связана со способом вызова методов.

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

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

Когда выполняется вызов данного метода:

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

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

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

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

8 голосов
/ 23 марта 2009

Расширение на правильный ответ Кента

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

  • Затенение: вызываемый метод зависит от типа ссылки в точке вызова
  • Переопределение: вызываемый метод зависит от типа объекта в момент выполнения вызова.
3 голосов
/ 23 марта 2009

Вот статья MSDN о теневом копировании. Примеры языков приведены в Visual Basic (к сожалению, в MSDN нет эквивалентной C # -страницы), но в целом она касается концепций и, надеюсь, в любом случае должна помочь вам понять.

Редактировать: Похоже, там - это a C # статья о теневом копировании, за исключением того, что она называется сокрытие в C # Кроме того, эта страница предлагает хороший обзор.

2 голосов
/ 11 апреля 2012

Если вы хотите скрыть метод базового класса, используйте переопределение в базе [виртуальный метод в базе]

если вы хотите скрыть метод дочернего класса, используйте new в базе [метод nonvirtual в базе] -> shadow

Base B=new Child()

B.VirtualMethod() -> Вызовы Дочерний метод класса

B.NonVirtualMethod() -> Вызовы метода базового класса

0 голосов
/ 14 июня 2018

Надеюсь, это краткое объяснение поможет.

Shadowing - заменяет полный элемент родительского класса

class InventoryAndSales
{
    public int InvoiceNumber { get; set; }
}

//if someone calls for this class then the InvoiceNumber type is now object 
class NewInventoryAndSales : InventoryAndSales
{
    public new object InvoiceNumber { get; set; }
}



Overriding - Заменяет только реализацию. Он не заменяет тип данных, который он не заменяет, например, если у вас есть переменная, он не преобразует его в метод, поэтому, если есть метод, он будет использовать этот метод и только изменил реализацию

 class InventoryAndSales
    {
        public virtual int GetTotalSales(int a, int b)
        {
            return a + b;
        }
    }


    class NewInventoryAndSales : InventoryAndSales
    {
        //it replaces the implementation in parent class
        public override int GetTotalSales(int a, int b)
        {
            return a * b;
        }
    }
0 голосов
/ 13 апреля 2018

Переопределение : то же имя и те же параметры, реализовано по-разному в подклассах.

  • Если рассматривать как DerivedClass или BaseClass, он использует производный метод.

Затенение : то же имя и точно такие же параметры, реализованные по-разному в подклассах.

  • Если рассматривать как DerivedClass, он использовал производный метод.
  • если рассматривается как BaseClass, он использует базовый метод.
0 голосов
/ 11 января 2012
 private static int x = 10;


static void Main(string[] args)
    { int x = 20;
        if (Program.x == 10)
        {
            Console.WriteLine(Program.x);
        }
        Console.WriteLine(x);}

Выход:

10 20

...