Написание выражений Upcasting и Downcasting в c # - PullRequest
0 голосов
/ 24 октября 2018

Я недавно изучал апскейтинг и апскейтинг в c #.Я понимаю, что апкастинг относится к преобразованию из производного класса в базовый класс.Однако, когда я вижу практический пример апскейтинга (как ниже), я запутываюсь.

public class Shape 
{
...
}

public class Circle : Shape
{
...
}

Circle circle = new Circle();
Shape shape = new Shape();
// Converting an object into its base class reference
shape = circle

Если мы конвертируем окружность в ссылку на базовый класс, не должно ли это быть похоже на

circle = shape 

Извините, если это звучит слишком любопытно.Это потому, что я всегда видел выражения в следующем формате:

int x = 3; // means assign 3 to variable x. 

Так что я просто запутался, почему круг находится справа, а не слева.Пожалуйста, порекомендуйте.Считай меня новичком.

Ответы [ 6 ]

0 голосов
/ 24 октября 2018

Upcasting означает изменение типа объекта на менее производный базовый класс (Circle object на Sape).

Downcasting работает в другом направлении, например.приведение от Shape к Circle.

Переменная более производного типа может быть легко назначена переменной менее производного типа, поскольку здесь выполняется неявное преобразование, поскольку Circle также является Shape.Вот почему значение более производного типа может быть присвоено переменной с менее производным типом.

Это не работает по-другому, поскольку Shape является общим, и мы не знаем, является ли оно Circle.Таким образом, когда вы пытаетесь использовать downcasting, вам нужно указать это явно:

// this won't work
Shape shape = new Shape();
Circle c = (Circle)shape;
// this will
Shape shape = new Circle();
// we know we have Circle object so we can downcast
Circle c = (Circle)shape;
0 голосов
/ 24 октября 2018

Я попытаюсь объяснить:

Переменная shape содержит ссылку на объект типа Shape.

Когда вы пишете Shape shape = new Shape(); Переменная shape будет содержать ссылку на новый объект Shape.

Когда вы переназначаете shape, записывая shape = circle, она содержит ссылкуна другой объект.Объект circle имеет тип circle, но так как окружность наследует shape, все в порядке, чтобы выполнить это назначение;существует неявное приведение circle к типу Shape.

Еще один и, возможно, более понятный способ сделать это приведение - сделать явное приведение:

Circle circle = new Circle();
Shape circleAsShape = (Shape)circle;
0 голосов
/ 24 октября 2018

если вы знаете о множестве, вы можете легко понять, почему «форма = круг» способна, «круг = форма» не может.

подумайте об этом.

А - этосимвол алфавита.

так что мы можем сказать

public class A : Alphabet
{
}

, как мы знаем.

также алфавит

public class Alphabet
{
}

, если мы рисуем диаграмму, это может быть так

┌───────── Alphabet ───────┐
│ A B C D E ... a b c ... z│
└──────────────────────────┘

Мы можем сказать, что z - это алфавит, но мы не можем сказать, что Alplabet - это z, потому что алфавит содержит больше, чем z.

Итак, давайте посмотрим на Круг и Форму.

Круг содержит информацию о Shape, и было добавлено больше переменных.(возможно, это не так, но можно изменить.)

Таким образом, мы можем сказать, что Circle - это набор Shape.

Мы можем модифицировать Circle, который основан на Shape.Также мы можем Инициализировать Circle.

, но если вы сделаете 'Shape = Circle', некоторые вещи, которые есть в Circle, не могут быть инициализированы.

, и он возвращает ошибку.

0 голосов
/ 24 октября 2018

Нет

Проблема в том, что: Shape - это не Circle, а Circle - это Shape.

Это означает, что Circle всегдаможет быть помещен в место, где требуется Shape, но когда вам нужен Circle, вы не можете бросить на его место любой Shape, так как это может быть также Triangle.

ЭтоВот почему вам нужно явно привести его в порядок (либо используя (Type)variable или variable as Type).

По существу, давайте предположим следующее:

class Shape {}
class Circle : Shape {}
class Triangle : Shape {}

Теперь у нас также есть Triangle что позволяет нам лучше разобраться в этом:

Circle c = new Circle();
Triangle t = c; // Impossible due to Circle not being a Triangle
Shape s = c; // Possible because a Circle is a Shape
Triangle t2 = s; // Impossible because Shape may be a Triangle or any other derived class
0 голосов
/ 24 октября 2018

(в сторону: это называется upcasting , потому что, как правило, диаграммы классов нарисованы так, что базовые классы физически отображаются над производными классами.)

Теперь, когда вы делаете:

shape = circle; // shape->(instance of Circle)

Вы присваиваете ссылку Circle для ссылки Shape, так что после назначения ссылка shape будет ссылаться на Circle.

Это нормальнопотому что все, что вы можете сделать с Shape, вы также можете сделать с Circle.

Если, однако, вы делаете:

circle = shape; // circle->(instance of Shape)

, вы назначаете Shapeссылка на Circle ссылку.Вы не можете сделать это, потому что (если бы это было возможно), вы могли бы получить доступ к Circle функциям, которых нет в Shape.

Например, представьте, что Circle.Radius существует, ноShape.Radius нет.

Если вам разрешено указывать ссылку circle на Shape, что произойдет, если вы попытаетесь получить доступ к circle.Radius?Ответ будет таким: неопределенное поведение произойдет, потому что Shape.Radius не существует.

0 голосов
/ 24 октября 2018

То, что вы в основном делаете в своем примере, также может быть записано следующим образом:

Circle circle = new Circle();
Shape shape = (Shape)circle; //Casting the object to the base type

Итак, вы приводите свой объект типа Circle к объекту типа Shape.В вашем коде это делается «автоматически», потому что вы присваиваете значение новой переменной типа Shape.

. Это объясняет немного более базовые / базовые классы: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/casting-and-type-conversions

...