Почему в этом случае выведется на экран "A"?
interface IPrinter
{
void Print();
}
public class A : IPrinter
{
public void Print()
{
Console.WriteLine("A");
}
}
public class B : A
{
public new virtual void Print()
{
Console.WriteLine("B");
}
}
public class C : B
{
public override void Print()
{
Console.WriteLine("C");
}
}
public class D : C
{
public override void Print()
{
Console.WriteLine("D");
}
}
internal class Program
{
public static void Main(string[] args)
{
IPrinter printer = new D();
printer.Print();
}
}
new virtual
ничего специально не значит, это просто два модификатора, указанные вместе.
Попробуем разобраться, что происходит в коде.
interface IPrinter
{
void Print();
}
public class A : IPrinter
{
public void Print()
{
Console.WriteLine("A");
}
}
Метод A.Print
становится реализацией объявления IPrinter.Print
, поскольку у него то же имя, те же параметры, и тот же тип возвращаемого значения (void
).
Теперь, когда мы приводим объект класса A
к типу IPrinter
и вызываем Print
на самом деле будет вызван A.Print
. Этот механизм работает похоже на переопределение виртуальных функций, но он немного сложнее.
Обратите внимание, что поскольку метод A.Print
не объявлен как виртуальный, его нельзя переопределить. Его можно только заменить с помощью new
.
public class B : A
{
public new virtual void Print()
{
Console.WriteLine("B");
}
}
Вот здесь метод Print
уже объявлен виртуальным, его можно переопределять в наследниках. Но поскольку родительский метод не-виртуальный, мы должны использовать ключевое слово new
, чтобы избавиться от предупреждения.
Что означает этот код? То, что поскольку метод A.Print
не виртуальный, мы теряем информацию о конкретном типе при приведении к базовому типу.
var b = new B()
b.Print(); // B
var a = b as A;
a.Print(); // A <- B.Print() не переопределяет A.Print(), а заменяет его, поэтому так
Чтобы нужно сделать, чтобы вызов a.Print()
печатал B, а не A?
public class A : IPrinter
{
public virtual void Print()
{
Console.WriteLine("A");
}
}
public class B : A
{
public override void Print()
{
Console.WriteLine("B");
}
}
Надо объявить метод виртуальным уже в классе A
, а в B
его переопределить.
В родительском IPrint классе метод Print не override, я уже точно не помню, но помоему чтобы его переопределить, override обязателен, но это не точно)
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Ситуация такаяЕсть dataGridView, в котором названия колонн прописываются программно
Есть 2 связанных таблицыДобавляя запись в одну, во вторую добавляется несколько связанных
У меня в представлении(Formcshtml) есть кнопка: <a href="~/Home/Form" type="button">Ввести данные</a>
Подскажите новичку в С# что не так, пожалуйстаЕсть форма, в которой заполняются поля 17-значными числами