Почему помеченный метод, который скрывает реализацию в базовом классе, может вызывать скрытый метод?

1

Я делал небольшое чтение вокруг спецификации С#, и натолкнулся на сценарий, которого я не ожидал, и надеялся, что кто-то может поделиться светом.

Я наткнулся на new ключевое слово, чтобы скрыть члены базового класса в производном классе, а затем несколько обсуждений о том, когда использовать new а не override virtual член.

Я бросил небольшой образец кода в мою IDE, ожидая увидеть ошибку компиляции

public class BaseType
{
    public void method()
    {
        // do nothing
    }
}
public class DerivedType : BaseType
{
    public new void method()
    {
        base.method();
    }
}

но вместо этого обнаружил, что это законный С#. Поскольку производный класс скрыл присутствие method(), почему мне все же позволено называть его?

ура

Теги:
inheritance

2 ответа

1
Лучший ответ

DerivedType скрывает метод от классов, которые будут наследовать DerivedType, а не от самого себя.
Обратите внимание, что для скрытия метода класс должен знать, что существует в нем метод родительского класса с тем же именем и теми же аргументами. Следовательно, один класс, скрывающий метод от его собственной сферы, нелогичен.

1

Не смешивайте метод со скрытием метода. Это два совершенно разных зверя.

Когда вы скрываете метод, вы скрываете его только при доступе к методу с помощью типа, который скрывает метод для начала:

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!"
} 
  • 0
    Хотя это является хорошим показателем разделения одного над другим, и это приветствуется, вопрос был больше, почему был опубликован законный c #, когда я ожидал, что это будет недействительным.
  • 0
    @JamieR Извините, я полностью неправильно понял ваш вопрос. Из любопытства, почему вы находите это удивительным, когда прячешься, а не когда переопределяешь?
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню