2016-11-01 3 views
2

Учитывая этот код:Тип объекта после литья?

class B 
{ 
    public virtual string Method() 
    { 
    return "base"; 
    } 
} 

class D : B 
{ 
    public override string Method() 
    { 
    return "derived"; 
    } 
} 

D d = new D(); 
B b = d as B; 
b.Method(); 

"производный" является выходом.

Но почему именно? Я имею в виду, b - новый объект типа B, не так ли? Или это тот же объект (в памяти), что и d? Если да, то каков тип времени выполнения b, а затем B или D?

Благодаря

+0

'b' имеет тип' B', но указывает на тот же объект, что и 'd', который имеет тип' D'. Тип исполнения также является «D». – Lee

+0

Не путайте со способом * hiding *. т. е. ключевое слово «новое». Если вы перепродаете * переопределить * с помощью * new *, он фактически напечатает '' base''. –

+0

это называется полиморфизмом во время выполнения –

ответ

3

Правило простое: b является ссылкой на объект типа D. Можно сказать, что тип времени выполнения b равен D, но это не особенно полезно для терминологии.

1

b новый объект типа B, не так ли?

Нет, b является существующий объект типа B, который указывает на тот же объект, созданный прямо над ним: d. Единственное различие заключается в том, что вы выбрали объект как его родительский тип - B, поэтому b рассматривается как B, а не более производный тип D.

Причина, по которой вы получаете вывод «производный», заключается в том, что метод переопределяется в производном классе, и это то, как работает надстройка. Просто потому, что вы объявляете переменную (т. Е. b), поскольку ее менее производный тип B не означает, что он еще не является фактически более производным типом D. Такова природа полиморфизма.

2

Вы можете сделать

B b = new D(); 
b.Method(); 

и вы все равно получите "получено". Как отметил @Bathsheba, важно то, что тип объекта не является ссылкой.

Представьте себе типичный пример объектно-ориентированного программирования, где у вас есть базовый класс Shape с производными классами Circle, Square и т.д. с виртуальным методом Area .. если у вас есть метод, как это:

void ShowArea(Shape shape) 
{ 
    Console.WriteLine(shape.Area()); 
} 

Тот факт, что ссылка не имеет значения (а фактический тип объекта) позволяет метод, как выше, чтобы принимать любой тип Shape и до сих пор печатать правильную область

0
B b = d as B; 

I б чтобы эта строка кода приводила только d к типу класса B, но значение по-прежнему остается «производным».