The_Unknown_Member Ответов: 1

Как работает полиморфизм для типов возвращаемых методов?


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

Например:
class SimpleClass
    {
        public SimpleClass ShallowCopy(SimpleClass sc)
        {
            return sc.MemberwiseClone();
        }
    }


Этот код не будет работать. Мне нужно предоставить явное приведение к возвращаемому значению. Но как это работает? Метод "MemberwiseClone()" из системы.Object возвращает объект. Поэтому, когда он возвращает объект, его тип должен быть только объектом? так ведь? Тогда почему я могу явно привести возвращаемое значение к SimpleClass? Как это работает? Может ли кто-нибудь объяснить мне это поведение?

Что я уже пробовал:

Почесываю в затылке. Исследуйте для получения дополнительной информации в Microsoft Docs, но там нет ничего подобного, объясненного там.

Maciej Los

Кажется, вы хотите использовать [в качестве оператора.

1 Ответов

Рейтинг:
5

OriginalGriff

Предположим, у вас есть три класса:

class A {}
class B : A { public string S { get; set ; } }
class C : B { public string S2 { get; set ; } }

Таким образом, C является производным от B, который является производным от A.
Это означает, что экземпляры обоих C & B являются экземплярами A плюс бит, и что экземпляр C также является экземпляром B. Но что а - это не в или С, А В-Не С.
A -> B -> C
Таким образом, совершенно очевидно, что вы можете назначить экземпляр B или C переменной типа A:
A a = new B();
a = new C();
Но вы не можете так что все наоборот:
B b = new C(); // Fine.
b = new A();   // ERROR!
Если бы вы могли, то у вас были бы проблемы, когда вы попытались получить доступ b.S потому что экземпляр A вообще не содержит переменной.

С этим - надеюсь - ясно, давайте посмотрим, что вы делаете.
return sc.MemberwiseClone();
MemberwiseClone возвращает an object потому что это базовый класс для всё - все остальные классы неявно являются производными от объекта. Поэтому когда вы возвращаете SimpleClass вы должны привести этот объект к вашему классу или я мог бы сделать это:
string LetSlipTheDogsOfWar(int i)
   {
   object o = i;  // perfectly legal, int is derived from object
   return o;
   }
...
string s = LetSlipTheDogsOfWar(666);  // Cry Havoc!

Система справедливо жалуется, что вы делаете что-то очень опасное!


The_Unknown_Member

Ну, в этом-то и вопрос. возвращаемый объект имеет тип System.Объект. Вопрос в том, почему можно привести возвращенную систему.Объект object to SimpleClass? В этом нет никакого смысла. Система.Объект-это не Симплекс, но Симплекс-это система.Объект

Edit: может быть, компилятор делает что-то за кулисами и заставляет производный метод MemberwiseClone() возвращать объект SimpleClass в реализации? Разве это не так? Такое поведение происходит только при использовании производного метода MemberwiseClone() из SimpleClass.

OriginalGriff

Вот именно! Простой класс - это объект, поэтому он "вписывается" в переменную объекта. Но в то же время это также и Симплекс, потому что это клон симплекса.
Метод MemberwiseClone наследуется от объекта, поэтому он может возвращать только объект. Чтобы использовать его, вы должны вернуть его к фактическому типу - и если это невозможно, вы получите ошибку времени выполнения.

- "Ха! Автозамена планшета!]

Maciej Los

Хорошо объяснил!
Это уже второй раз за сегодняшний день, когда я публикую такой комментарий...

Кстати: что вы думаете о моем комментарии к этому вопросу?

OriginalGriff

TBH, я обычно использую "as", но в этом случае я бы использовал "правильное" приведение специально для получения исключения runtime cat вместо возврата нулевого значения - это яснее (по крайней мере для меня), в чем проблема таким образом.

BillWoodruff

+5