Почему помеченный метод, который скрывает реализацию в базовом классе, может вызывать скрытый метод?
Я немного читал о спецификациях C# и натолкнулся на сценарий, которого не ожидал, и надеялся, что кто-нибудь поделится каким-то осмыслением.
Я наткнулся через new
ключевое слово для сокрытия членов базового класса в производном классе, а затем несколько обсуждений о том, когда использовать new
в отличие от override
на virtual
член.
Я добавил небольшой пример кода в мою среду IDE, ожидая увидеть ошибку компиляции
public class BaseType
{
public void method()
{
// do nothing
}
}
public class DerivedType : BaseType
{
public new void method()
{
base.method();
}
}
но вместо этого обнаружил, что это законно C#. Так как производный класс скрыл присутствие method()
почему мне все еще разрешено это называть?
ура
2 ответа
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!"
}