Ответ 1
new
модификатор заставляет скрыть элемент, который разбивает полиморфные отношения в вашей иерархии классов. Метод SayHi
B
рассматривается как отличный (не переопределяющий) из A
s (таким образом, выбор слова "новый" как ключевое слово). C
s затем переопределяет B
s, а не A
s (который остается скрытым).
Поэтому, когда вы вызываете SayHi
в экземпляре C
с помощью ссылки A
, среда выполнения будет разрешать его по типу A
, а не по типу C
(внутри которого SayHi
является "новый" метод, унаследованный от B
).
Если, с другой стороны, вы должны были запустить:
B p = new C();
p.SayHi();
... вы получите ожидаемый полиморфный результат:
From C
Изменить. Так как вы запросили прецедент, то один. До появления родословных в .NET Framework 2.0 иногда сглаживание элементов использовалось как средство изменения возвращаемых типов унаследованных методов в производных классах (что нельзя делать при переопределении), чтобы возвращать более конкретные типы. Например:
class ObjectContainer
{
private object item;
public object Item
{
get { return item; }
set { item = value; }
}
}
class StringContainer : ObjectContainer
{
public new virtual string Item
{
get { return base.Item as string; }
set { base.Item = value as string; }
}
}
class QuotedStringContainer : StringContainer
{
public override string Item
{
get { return "\"" + base.Item + "\""; }
}
}
Свойство Item
класса ObjectContainer
возвращает простой object
. Однако в StringContainer
это унаследованное свойство скрыто для возврата a string
. Таким образом:
ObjectContainer oc = new StringContainer();
object o = oc.Item; // Valid, since ObjectContainer.Item is resolved
string s1 = oc.Item; // Not valid, since ObjectContainer.Item is still resolved
string s2 = ((StringContainer)oc).Item;
// Valid, since StringContainer.Item is now resolved
Класс QuotedStringContainer
переопределяет свойство Item
StringContainer
, наследуя его возвращаемый тип string
; однако он все еще скрыт от свойства object
-returning Item
ObjectContainer
. Если бы это было не так, не было бы способа примирить их разрозненные типы возврата...
ObjectContainer oc = new QuotedStringContainer();
object o = oc.Item; // Valid, since ObjectContainer.Item is resolved
string s1 = oc.Item; // Not valid, since ObjectContainer.Item is still resolved
string s2 = ((StringContainer)oc).Item;
// Valid, since QuotedStringContainer.Item is now resolved
// (polymorphism!)
string s3 = ((QuotedStringContainer)oc).Item;
// Valid, since QuotedStringContainer.Item is now resolved