Відповіді:
Ну спадок ...
припустимо, у вас є такі класи:
class A {
public int Foo(){ return 5;}
public virtual int Bar(){return 5;}
}
class B : A{
public new int Foo() { return 1;} //shadow
public override int Bar() {return 1;} //override
}
то коли ви телефонуєте цьому:
A clA = new A();
B clB = new B();
Console.WriteLine(clA.Foo()); // output 5
Console.WriteLine(clA.Bar()); // output 5
Console.WriteLine(clB.Foo()); // output 1
Console.WriteLine(clB.Bar()); // output 1
//now let's cast B to an A class
Console.WriteLine(((A)clB).Foo()); // output 5 <<<-- shadow
Console.WriteLine(((A)clB).Bar()); // output 1
Припустимо, у вас базовий клас і ви використовуєте базовий клас у всьому своєму коді замість успадкованих класів, а ви використовуєте тінь, він поверне значення, які базовий клас повертає замість того, щоб слідувати дереву спадкування реального типу об'єкта.
Сподіваюся, я маю сенс :)
Тінізація - це фактично VB мова, що ми б називали приховуванням у C #.
Часто приховування (затінення у VB) та переосмислення показано як відповідь Stormenet .
Показано, що віртуальний метод перекритий підкласом, і виклики до цього методу навіть для типу суперкласу або з внутрішнього коду надкласового виклику реалізують заміну з підкласу.
Потім показується конкретний метод (який не позначений як віртуальний або абстрактний), прихований за допомогою newключового слова при визначенні методу з ідентичною підписом на підкласі. У цьому випадку, коли метод викликається надкласовим типом, використовується оригінальна реалізація, нова реалізація доступна лише для підкласу.
Однак часто пропускають те, що також можна приховати віртуальний метод.
class A
{
public virtual void DoStuff() { // original implementation }
}
class B : A
{
public new void DoStuff() { //new implementation }
}
B b = new B();
A a = b;
b.DoStuff(); //calls new implementation
a.DoStuff(); //calls original implementation.
Зауважте у наведеному вище прикладі DoStuff стає конкретним і його неможливо перекрити. Однак також можна використовувати як virtualі newключові слова разом.
class A
{
public virtual void DoStuff() { // original implementation }
}
class B : A
{
public new virtual void DoStuff() { //new implementation }
}
class C : B
{
public override void DoStuff() { //replacement implementation }
}
C c = new C();
B b = c;
A a = b;
c.DoStuff(); //calls replacement implementation
b.DoStuff(); //calls replacement implementation
a.DoStuff(); //calls original implementation.
Зауважимо, що незважаючи на те, що всі методи, що стосуються віртуальності, переосмислення на C не впливає на віртуальний метод на A через те, що використання newв B приховує реалізацію A.
Редагувати: У коментарях до цієї відповіді було зазначено, що вищесказане може бути небезпечним або, принаймні, не особливо корисним. Я б сказав, що так, це може бути небезпечно і було б там, якби воно було взагалі корисним.
Зокрема, ви можете зіткнутися з усілякими проблемами, якщо також зміните модифікатори доступності. Наприклад:-
public class Foo
{
internal Foo() { }
protected virtual string Thing() { return "foo"; }
}
public class Bar : Foo
{
internal new string Thing() { return "bar"; }
}
До зовнішньої спадкоємиці Bar, Fooреалізація «s речі () залишається і перевизначенням під'їзду. Всі юридичні та пояснювані згідно з правилами типу .NET ніколи не зовсім інтуїтивні.
Я опублікував цю відповідь, щоб поглибити розуміння того, як все працює не як пропозиція про методи, якими можна вільно користуватися.
Я думаю, що головна відмінність полягає в тому, що за допомогою затінення ви, по суті, повторно використовуєте ім'я та просто ігноруєте використання суперкласу. З переосмисленням ви змінюєте реалізацію, але не доступність та підпис (наприклад, типи параметрів та повернення). Див. Http://www.geekinterview.com/question_details/19331 .
Shadowing - це концепція VB.NET. У C # Shadowing відомий як приховування. Він приховує похідний метод класу. Це здійснюється за допомогою ключового слова "new".
Ключове слово Override використовується для забезпечення абсолютно нової реалізації методу базового класу (який позначений "Virtual") у похідному класі.
Якщо у вас є щось подібне нижче,
Class A
{
}
Class B:A
{
}
A a = new B();
Будь-який метод, який ви викликаєте на об'єкт 'a', буде зроблений на тип 'a' (тут тип - A), але якщо ви реалізуєте той самий метод у класі B, який вже присутній у класі A, компілятор буде надати вам попередження про використання ключового слова "Нове". Якщо ви використовуєте "Нове", попередження зникне. Крім цього немає різниці між використанням "Нового" або не використанням його у спадковому класі.
У деяких ситуаціях вам може знадобитися викликати метод референтного класу, який утримує конкретний екземпляр у той момент, а не викликати метод типу об'єкта. У наведеному вище випадку посилання, яке він має, - "B", а тип - "A". Отже, якщо ви хочете, щоб виклик методу повинен відбуватися на "B", тоді ви використовуєте Virtual і переосмислюєте це для досягнення.
Сподіваюся, це допомагає ...
Даніель Сандіп.
Якщо є випадок, коли ви не можете змінити вміст класу, скажімо A, але ви хочете використовувати його деякі методи разом із вами методом, ім'я якого є загальним, ви можете використовувати власну реалізацію методуnew ключовим словом.
Суть в тому, щоб використовувати його в тому, що і еталон, і об'єкт повинні бути одного типу.
class A
{
public void Test()
{
Console.WriteLine("base");
}
}
class B : A
{
public new void Test()
{
Console.WriteLine("sub");
}
public static void Main(string[] args)
{
A a = new A();
B aa = new B();
a.Test();
aa.Test();
}
}