Читайте также:
|
|
Если присвоить объект производного класса (Rectangle) переменной базового класса (Shape), как ниже:
Shape myShape = new Rectangle();
часть информации об объекте Rectangle будет утрачена. Теперь нельзя четко определить, относится ли myShape к типу Rectangle, или Triangle. Чтобы убедится в этом, добавим в класс Circle новую переменную. Даже если известно, что myShape содержит Circle, попытка обратиться к свойству Radius с помощью оператора:
myShape.Radius = 20.4; //Неверно
приведет к ошибке, поскольку в момент компиляции неизвестно, указывает ли myShape на объект типа Rectangle, Triangle или Circle.
Для примера создадим объект аналогичного класса:
Circle myCircle = new Circle();
myCircle.Radius = 5;
Console.WriteLine(myCircle.Radius);
В данном случае код будет верен, т.к. тип переменной экземпляра Circle myCircle совпадает с классом Circle.
В случае, когда мы вызываем метод следующим образом:
myShape = new Triangle();
myShape.DrawYouself();
Пока вызываются только те элементы класса Rectangle, которые определены и в Shape, ограничение в доступе не проявляется.
Упакуем созданные объекты в некий массив. Напоминаю, что массив должен содержать элементы одного типа, в данном случае типа Shape. Фрагмент кода имеет вид:
Shape[] ShapeCollection = new Shape[3];
ShapeCollection[0] = new Triangle();
ShapeCollection[1] = new Rectangle();
ShapeCollection[2] = new Circle();
for (int i = 0; i < ShapeCollection.Length; i++)
{
ShapeCollection[i].DrawYouself();
}
В программе черчения, например, реальное содержимое элементов массива ShapeCollection типа Shape не требовалось, поскольку вызывался только метод DrawYotirself (посредством динамического связывания).
Дело обстоит иначе, когда нужно вызвать функцию-член, специфичную для класса Circle. Например, пусть требуется подсчитать общую площадь окружностей на чертеже.
Стандартное обращение к переменной Radius не дает результата, поскольку элементы ShapeCollection принадлежат типу Shape и не поддерживают обращения к Radius. Если бы можно было четко определить, что в элементе хранится объект типа Circle и затем преобразовать переменную к этому типу, можно было бы и обратиться к свойству Radius.
К счастью, С# следит за тем, на какой объект (и какого типа) указывает переменная в каждый момент времени. (Иначе не реализовать механизм динамического связывания.) Для доступа к этой информации в программе применяются операции is и as, представленные далее. Операция is позволяет проверить, является ли переменная (например, myShape) указателем на объект определенного типа (например, Circle). Результат ее — логическое значение true или false. Чтобы проверить, содержит ли myShape объект Circle, используется логическое выражение:
myShape is Circle,
которое возвращает true, если myShape указывает на Circle, и false — в противном случае.
Если в myShape хранится Circle, эту переменную можно преобразовать к типу Circle и обратиться к свойству Radius. Для этого применяется операция приведения типа.
Оператор присваивания
Shape myShape = new Circle();
показывает, что объект класса Circle можно присвоить переменной myShape типа Shape. Это возможно, поскольку класс Circle — производный от класса Shape, т. е. все элементы класса, доступные в Shape, доступны и в Circle. Shape в иерархии выше, чем Circle, и такое присваивание требует восходящего приведения типа.
ыо не указано явно. В отличие с
Движение в противоположном направлении, с приведением переменной к типу, расположенному в иерархии ниже, называется нисходящим приведением типа. Нисходящее приведение создает некоторые трудности. Например, нельзя использовать оператор вида:
Circle myCircle = myShape;
поскольку myShape может также содержать Rectangleили Triangle, а эти классы могут и не иметь элементов, к которым можно обращаться через Circle. Тем не менее, если известно, что myShape фактически указывает на объект Circle, можно воспользоваться явным приведением типа:
Circle myCircle = (Circle)myShape;
Отсюда следует правило. Если объект класса А приводится к классу В, причем А — потомок В, это называется восходящим приведением. При этом не требуется явной операции приведения типа. Если же А — предок В, это называется нисходящим приведением. Нисходящее приведение всегда требует явной операции (<Tип>).
Используя операцию is(позволяющую узнать, указывает ли переменная на объект определенного типа) и операцию нисходящего приведения типа, можно решить проблему с Circle и вычислить общую площадь объектов этого типа в массиве ShapeCollection.
Дата добавления: 2015-10-23; просмотров: 112 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Вопрос 13 Полиморфизм как концепция ООП. | | | Вопрос 29 Текстовые поля. Элемент управления Label и TextBox. Сравнительный анализ. |