2016-05-08 10 views
2

В случае переопределения метода на основе метода вызова метода референтного объекта будет принято решение. В случае скрытия метода в зависимости от типа метода вызова метода будет принято решение.Метод скрытия плюс переопределяющее решение о вызове

Может ли кто-нибудь объяснить мне метод, вызывающий решение при переопределении + скрытии.

public class Base 
    { 
     public virtual void DoIt() 
     { 
     } 
    } 

    public class Derived : Base 
    { 
     public override void DoIt() 
     { 
     } 
    } 

    public class Derived1 : Derived 
    { 
     public new void DoIt() 
     { 
     } 
    } 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      Base b = new Derived(); 
      Derived d = new Derived(); 
     #1 b.DoIt();      // Calls Derived.DoIt 
     #2 d.DoIt();      // Calls Derived.DoIt 
      b = new Derived1(); 
      d = new Derived1(); 
     #3 b.DoIt();      // Calls Derived.DoIt 
     #4 d.DoIt(); 
} 
} 

# 1 и # 2 вызов Derived.DoIt из-за полиморфизма во время выполнения.

# 4 называется Derived.DoIt, потому что d имеет тип Dreived (метод скрывается).

Но почему № 3 называется Derived.DoIt.

Что такое вызывающая последовательность в случае преодоления плюс скрытия в C#.

Заранее спасибо

+0

Вы можете думать об этом так: 'Derived1' имеет два' методы DoIt' - один унаследованные от класса 'Base', а другие объявленной прямо в' Derived1 сам. Когда вы вызываете DoIt в экземплярах типа Base или Derived - они знают только об одном методе DoIt и не знают о другом, поэтому этот вызов вызывается. – Evk

ответ

0

# 3 вызовы Derived.DoIt(), так как метод был только скрыт, он по-прежнему внешне вызываемым при использовании соответствующего актерский. Переменная b имеет тип Base, поэтому вы получаете доступ к методам, доступным для Base. Это тот, который перезаписывается через Derived, поэтому ваш результат является результатом Derived.DoIt. Если бы у вас была переменная типа Derived1 и сделал вызов DoIt, Derived1.DoIt был бы вызван вместо этого.

public class Base 
{ 
    public virtual void DoIt() 
    { 
     Console.WriteLine("Base.DoIt was called!"); 
    } 
} 

public class Derived : Base 
{ 
    public override void DoIt() 
    { 
     Console.WriteLine("Derived.DoIt was called!"); 
    } 
} 

public class Derived1 : Derived 
{ 
    public new void DoIt() 
    { 
     Console.WriteLine("Derived1.DoIt was called!"); 
    } 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 

     Base b = new Derived(); 
     Derived d = new Derived(); 
     Console.WriteLine("#1"); 
     b.DoIt();      
     Console.WriteLine("#2"); 
     d.DoIt();      
     b = new Derived1(); 
     d = new Derived1(); 
     Console.WriteLine("#3"); 
     b.DoIt();      
     Console.WriteLine("#4"); 
     d.DoIt(); 
     Console.WriteLine("#5"); 
     Derived1 e = new Derived1(); 
     e.DoIt(); 
     Console.ReadKey(); 
    } 
} 
1

Потому что # 3 - это экземпляр типа Base. Здесь последний производный метод Base находится в классе Derived и, следовательно, он вызывается.

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

1

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

Выполнение производного класса get скрыто от базового класса.

Если вы пишете так:

b = new Derived1(); 
b.DoIt() // (run-time) will call Dervied method implementation as Dervied has overridden 
     // so calling via base reference will call overridden implementation if any 
     //otherwise base class implementation will get called 

Derived1 d1 = (Derived1)b; 
d1.DoIt(); // (compile time) will call Derived1 method implementation due to hiding in Derived1 
Derived d = (Derived)b; 
d.DoIt(); // (run-time) will call Derived method implementation due to override