Книга: C# для профессионалов. Том II

Ссылки на производные классы

Ссылки на производные классы

Подробнее рассмотрим класс Manager, на который ссылается переменная, объявленная как ссылка на Employee:

Employee Elton = new Manager("Elton John", 50000.00M);

Это на самом деле совершенно законный синтаксис C#. Правило вполне простое: если объявлена ссылка на некоторый тип данных В, то этой ссылке разрешается ссылаться на экземпляры В или экземпляры любого производного из В класса. Это работает, так как любой класс, производный из В, должен также реализовать все методы или свойства и т.д., которые реализует класс В. Поэтому в примере выше вызывается Elton.Name, Elton.Salary и Elton.GetMonthlyPayment(). Тот факт, что Employee реализует все эти члены, гарантирует, что любой класс, производный из Employee, также будет это делать. Поэтому не имеет значения, указывает ли ссылка на производный класс — мы по-прежнему сможем использовать эту ссылку для вызова любого члена класса, на который определена ссылка, и будем уверены, что этот метод существует в производном классе.

С другой стороны, отметим синтаксис, который использовался при вызове свойства Bonus на объекте Elton: ((Manager)Elton).Bonus. В этом случае необходимо явно преобразовать Elton в ссылку на Manager, так как Bonus не реализовано в Employee. Компилятор знает это и будет создавать ошибку компиляции, если попробовать вызвать Bonus через ссылку на Employee. Данная строка кода является на самом деле сокращением записи:

Manager ManagerElton = (Manager)Elton;
this.listBox1.Items.Add("Elton's bonus is " + ManagerElton.Bonus);

Как и в VB, преобразование между типами данных в C# называется преобразованием типов (casting). Можно заметить в приведенном выше коде, что синтаксис преобразования типов включает размещение имени типа данных в скобках перед именем переменной, преобразование которой собираются выполнить. Конечно, указанный объект должен содержать прежде всего правильный тип данных. Если в этом примере написать:

Manager ManagerBritney = (Manager)Britney;

то код будет компилироваться правильно, но при его работе будет получена ошибка, так как среда выполнения .NET определит, что Britney является только экземпляром Employee, а не Manager. Ссылкам разрешается ссылаться на экземпляры производных классов, но не на экземпляры базовых классов своего собственного типа. Не разрешается ссылке на Manager ссылаться на объект Employee. (Это недопустимо, так как подумайте, что произойдет, если попытаться вызвать свойство Bonus с помощью такой ссылки.)

Кстати, совершенно не рассматривались подробности возникновения ошибки во время выполнения. На самом деле C# имеет для такого случая очень развитый механизм, называемый исключениями, который кратко будет показан позже.

Так как VB не поддерживает наследование реализации, то не существует прямой параллели в VB для поддержки ссылок, указывающих на объекты производных классов, как в C#. Однако это напоминает VB — можно объявить ссылку на интерфейс, при этом не имеет значения, на какой тип объекта ссылается интерфейс, пока этот объект реализует интерфейс. Если бы классы Employee и Manager кодировались в VB, можно было вполне сделать так, определяя интерфейс IEmployee, который реализуют оба модуля классов, и затем обращаться к свойствам Employee через этот интерфейс.

Оглавление книги


Генерация: 1.892. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз