Я делал небольшое чтение вокруг спецификации С#, и натолкнулся на сценарий, которого я не ожидал, и надеялся, что кто-то может поделиться светом.
Я наткнулся на new
ключевое слово, чтобы скрыть члены базового класса в производном классе, а затем несколько обсуждений о том, когда использовать new
а не override
virtual
член.
Я бросил небольшой образец кода в мою IDE, ожидая увидеть ошибку компиляции
public class BaseType
{
public void method()
{
// do nothing
}
}
public class DerivedType : BaseType
{
public new void method()
{
base.method();
}
}
но вместо этого обнаружил, что это законный С#. Поскольку производный класс скрыл присутствие method()
, почему мне все же позволено называть его?
ура
DerivedType
скрывает метод от классов, которые будут наследовать DerivedType
, а не от самого себя.
Обратите внимание, что для скрытия метода класс должен знать, что существует в нем метод родительского класса с тем же именем и теми же аргументами. Следовательно, один класс, скрывающий метод от его собственной сферы, нелогичен.
Не смешивайте метод со скрытием метода. Это два совершенно разных зверя.
Когда вы скрываете метод, вы скрываете его только при доступе к методу с помощью типа, который скрывает метод для начала:
public class Foo
{
public string Blah() { return "Hi from Foo!"; }
}
public class DerivedFoo: Foo
{
public new string Blah() { return "Hi from DerivedFoo!"; }
}
Теперь мы имеем следующее поведение:
void TestFoos()
{
Foo foo = new Foo();
DerivedFoo derivedFoo = new DerivedFoo();
Foo derivedFooInDisguise = derivedFoo as Foo;
Console.WriteLine(foo.Blah()); //Outputs "Hi from Foo!"
Console.WriteLine(derivedFoo.Blah()); //Outputs "Hi from DerivedFoo!"
Console.WriteLine(derivedFooInDisguise.Blah()); //Outputs "Hi from Foo!"
}
Обратите внимание, что это поведение одинаково, даже если Blah
объявлен как virtual
. Интересная часть - третий звонок. Метод вызывается через Foo
типизированный объект. Поскольку это не виртуальный вызов, Foo.Blah()
, а не DerivedFoo.Blah()
.
Теперь это полностью отличается от переопределения метода, когда вызов виртуального метода всегда разрешает тип времени выполнения объекта, а не тип, через который вы его вызываете:
public class Foo
{
public virtual string Blah() { return "Hi from Foo!"; }
}
public class DerivedFoo: Foo
{
public override string Blah() { return "Hi from DerivedFoo!"; }
}
Теперь мы имеем следующее поведение:
void TestFoos()
{
Foo foo = new Foo();
DerivedFoo derivedFoo = new DerivedFoo();
Foo derivedFooInDisguise = derivedFoo as Foo;
Console.WriteLine(foo.Blah()); //Outputs "Hi from Foo!"
Console.WriteLine(derivedFoo.Blah()); //Outputs "Hi from DerivedFoo!"
Console.WriteLine(derivedFooInDisguise.Blah()); ////Outputs "Hi from DerivedFoo!"
}
Derived
.