Сокрытие C#, переопределение и вызывание функции от базового класса

Я изучаю C#, и я встретился со следующей проблемой. У меня есть два класса: базируйтесь и полученный:

class MyBase
{
    public void MyMethod()
    {
        Console.WriteLine("MyBase::MyMethod()");
    }
}


class MyDerived: MyBase
{
    public void MyMethod()
    {
        Console.WriteLine("MyDerived::MyMethod()");
    }
}

На данный момент, без virtual и override ключевые слова. Когда я компилирую это, я получаю предупреждение (который, конечно, ожидается), что я пытаюсь скрыться MyMethod от MyBase класс.

То, что я хочу сделать, должно назвать метод от базового класса, имеющего экземпляр производного класса. Я делаю это как это:

MyDerived myDerived = new MyDerived();
((MyBase)myDerived).MyMethod();

Это хорошо работает, когда я не указываю никого virtual, и т.д. ключевые слова в методах. Я пытался поместить комбинацию ключевых слов, и я получил следующие результаты:

| MyBase::MyMethod | MyDerived::MyMethod | Result printed on the console |
| -----------------|---------------------|-------------------------------|
| -                | -                   | MyBase::MyMethod()            |
| -                | new                 | MyBase::MyMethod()            |
| virtual          | new                 | MyBase::MyMethod()            |
| virtual          | override            | MyDerived::MyMethod()         |

Я надеюсь, что таблица ясна Вам. У меня есть два вопроса:

  1. Действительно ли это - корректный способ вызвать функцию от базового класса (((MyBase)myDerived).MyMethod();)? Я знаю о base ключевое слово, но это можно назвать только с внутренней части производного класса. Действительно ли это правильно?
  2. Почему в последнем случае (с virtual и override модификаторы), метод, который назвали, прибыл из производного класса? Объясните это?
15
задан dbc 12 May 2019 в 06:22
поделиться

4 ответа

Когда вы вызываете виртуальный метод для экземпляра типа, который переопределяет метод, всегда будет вызываться переопределенная версия, даже если вы приведете к базовому классу.

Единственный способ вызвать базовую реализацию виртуального метода в классе, который переопределяет метод, - это создать второй метод в производном классе (не в базовом классе), который вызывает метод с использованием base ] ключевое слово.

В общем, необходимость сделать это является признаком плохой разработки API - если вы думаете, что вам нужно вызвать базовую версию, производная версия, вероятно, должна иметь другое имя.

18
ответ дан 1 December 2019 в 02:55
поделиться

Вы правы - base можно вызывать только из производного класса - Source .

На этой странице также приведен пример того, как переопределить определение базового класса.

2
ответ дан 1 December 2019 в 02:55
поделиться

Что касается вашего второго вопроса, вы меняете не тип объекта, на который вы ссылаетесь, а только интерфейс, через который вы на него ссылаетесь. Поэтому, если у вас есть объект B, который наследуется от A и переопределяет функцию C, даже если вы ссылаетесь на B как на A, он все равно вызывает реализации наиболее производного типа, в данном случае B.

3
ответ дан 1 December 2019 в 02:55
поделиться
  1. Вы правы, base ссылается на в базовый класс для данного экземпляра.
  2. Этот механизм называется полиморфизмом: лучше работать без предупреждения. Естественно-объектно-ориентированный хороший способ - это последний из упомянутых вами случаев.

Между прочим, старайтесь избегать написания кода, обеспечивающего соблюдение принципа подстановки, другими словами, не пишите код, который зависит от реализации вашей иерархии классов, потому что вам придется изменить этот код, если вы добавите новый производный класс для вашего базового класса.

2
ответ дан 1 December 2019 в 02:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: