Унаследованный метод не имеет доступа к новой реализации в производном классе
Как указано в этой статье MSDN:
Объект типа производного класса не имеет доступа к новому переопределенному методу, унаследованному от базового класса, и к вызову объекта производного класса из ShowDetails()
Метод внутри унаследованного метода DescribeCar()
сделано в ShowDetails()
Метод базового класса.
если DescribeCar()
Метод также доступен для ConvertibleCar
класс, почему так не видно так называемого new ShowDetails()
Метод?
class Car
{
public void DescribeCar()
{
System.Console.WriteLine("Four wheels and an engine.");
ShowDetails();
}
public virtual void ShowDetails()
{
System.Console.WriteLine("Standard transportation.");
}
}
// Define the derived classes.
// Class ConvertibleCar uses the new modifier to acknowledge that ShowDetails
// hides the base class method.
class ConvertibleCar : Car
{
public new void ShowDetails()
{
System.Console.WriteLine("A roof that opens up.");
}
}
class Program
{
static void Main(string[] args)
{
ConvertibleCar car2 = new ConvertibleCar();
car2.DescribeCar();
}
}
//output
// Four wheels and an engine.
// Standard transportation.
3 ответа
new
скрывает старый метод, что означает, что если вы напрямую вызываете его на ConvertibleCar
Например, вы получите поведение производного класса, но оно не будет вызываться полиморфно.
Когда базовый класс вызывает его, он вызывает виртуальный метод, который, поскольку он не был переопределен, вызывает метод базового класса. Вместо использования метода скрытия (который вы почти никогда не используете), просто переопределите его:
class ConvertibleCar : Car
{
public override void ShowDetails()
{
System.Console.WriteLine("A roof that opens up.");
}
}
Ну, когда вы думаете об этом - не думайте о наследовании - это все равно что спрашивать, почему Car.DescribeCar
не имеют доступа к ConvertibleCar.ShowDetails
,
ConvertibleCar.ShowDetails
по сути, это метод, который не является членом Car
если хотите - из-за new
ключевое слово. Car
Однако есть метод ShowDetails
,
Car.DescribeCar
как метод члена Car
имеет видимость Car.ShowDetails
и не ConvertibleCar.ShowDetails
таким образом Car.ShowDetails
это то, что вызывается.
Может быть, это будет понятнее. С new
ключевое слово, это еще один способ думать об этом:
class Car
{
...
public virtual void ShowDetails(){..}
}
class ConvertibleCar : Car
{
public void new_ShowDetails(){}
}
Car
не знает ConvertibleCar.new_ShowDetails
поэтому не может вызвать метод.
Другие ответы верны, но я хочу показать пример того, что происходит внутри DescribeCar()
метод.
public void DescribeCar()
{
Type t = this.GetType();
//bad hack
dynamic _this = Convert.ChangeType(this, t);
this.ShowDetails(); //Prints "Standard transportation."
_this.ShowDetails(); //Prints "A roof that opens up."
}
t
является ConvertibleCar
потому что это фактический тип объекта, но this
переменная (которая на самом деле является параметром каждого нестатического метода, скрытого компилятором) имеет тип Car
,
Конкретная вещь о virtual
методы в том, что когда они вызываются вашим кодом, компилятор выполняет дополнительный поиск фактического типа объекта (т.е. вызывает GetType()
) и проверяет, переопределил ли какой-либо тип в вашей иерархии метод. Затем он вызывает новейшую реализацию вашего метода. Но если вы используете new
вместо override
этот поиск не дает результатов и используется базовая реализация. Если вы используете new
единственный способ вызвать новую реализацию - привести вашу переменную к типу, в котором была определена новая реализация.