Ранее мы уже говорили о преобразовании простейших типов. Теперь затронем тему преобразования объектов различных классов. Итак, у нас есть следующая система классов:
'Классы Public MustInherit Class Person Public Property FirstName() As String Public Property LastName() As String 'Абстрактный метод Public MustOverride Sub Display() Public Sub New(fName As String, lName As String) FirstName = fName LastName = lName End Sub End Class Public Class Employee Inherits Person Public Property Bank As String Public Overrides Sub Display() Console.WriteLine(FirstName & " " & LastName & " works in " & Bank) End Sub Public Sub New(fName As String, lName As String, _bank As String) MyBase.New(fName, lName) Bank = _bank End Sub End Class Public Class Client Inherits Person Implements IAccount 'Переменная для хранения суммы Dim _sum As Integer 'Переменная для хранения процента Dim _procentage As Integer Public Property Bank As String 'Текущая сумма на счете ReadOnly Property CurentSum() As Integer Implements IAccount.CurentSum Get Return _sum End Get End Property 'Метод для добавления денег на счет Sub Put(sum As Integer) Implements IAccount.Put _sum += sum End Sub 'Метод для снятия денег со счета Sub Withdraw(sum As Integer) Implements IAccount.Withdraw If sum <= CurentSum Then _sum -= sum End If End Sub 'Процент начислений ReadOnly Property Procentage() As Integer Implements IAccount.Procentage Get Return _procentage End Get End Property Public Overrides Sub Display() Console.WriteLine(FirstName & " " & LastName & " has an account in bank " & Bank) End Sub Public Sub New(fName As String, lName As String, _bank As String, _sum As Integer) MyBase.New(fName, lName) Bank = _bank Me._sum = _sum End Sub End Class 'Интерфейсы Public Interface IAccount 'Текущая сумма на счете ReadOnly Property CurentSum() As Integer 'Метод для добавления денег на счет Sub Put(sum As Integer) 'Метод для снятия денег со счета Sub Withdraw(sum As Integer) 'Процент начислений ReadOnly Property Procentage() As Integer End Interface Public Interface IDepositAccount Inherits IAccount 'Начисление процентов Sub GetIncome() End Interface
В иерархии классов мы можем проследить следующую цепь наследования: Object (все классы неявно наследуются от типа Object) -> Person -> Employee|Client.
Из этой цепи видно, что объект класса Client
одновременно является и представителем классов Person и Object. Поэтому мы можем
создать объекты обоих классов следующим образом:
Dim emp As Object = New Employee("John", "Thompson", "City Bank") Dim cl As Person = New Client("Tom", "Johnson", "City Bank", 100) emp.Display() cl.Display()
В данном случае работает неявное преобразование, так как наши переменные представляют классы Object
и Person
, поэтому
допустимо неявное восходящее преобразование - преобразование к типам, которые находятся вверху иерархии классов:
Object
|
Person
|
Employee|Client
Таким образом, классы Employee и Client находятся в низу иерархии классов. Добавим еще класс Manager, который будет производным от Employee и поэтому будет находиться в самом низу иерархии классов.
Public Class Manager Inherits Employee Public Overrides Sub Display() Console.WriteLine(FirstName & " " & LastName & " is a manager of " & Bank) End Sub Public Sub New(fName As String, lName As String, _bank As String) MyBase.New(fName, lName, _bank) End Sub End Class
Значит, мы можем написать следующее, так как объект класса Manager в то же время является и сотрудником банка:
Dim man As Employee = New Manager("John", "Thompson", "City Bank") man.Display()
В то же время, если мы применим нисходящее преобразование, как в следующем коде, то мы получим ошибку:
Dim emp As Manager = New Employee("John", "Thompson", "City Bank") emp.Display()
Здесь мы преобразуем объект Emloyee к типу Manager, однако если Manager является объектом типа Emloyee, то объект Emloyee не является объектом типа Manager. Есть несколько способов избежать ошибки при выполнении программы. Во-первых, можно использовать оператор TryCast - он пытается преобразовать выражение к определенному типу, при этом не выбрасывает исключение. В случае неудачного преобразования выражение будет содержать значение Nothing:
Dim emp As New Employee("John", "Thompson", "City Bank") Dim man As Manager = TryCast(emp, Manager) If man Is Nothing Then Console.WriteLine("Преобразование прошло неудачно") Else man.Display() End If
Второй способ заключается в отлавливании исключения InvalidCastException, которое возникнет в результате преобразования:
Try Dim emp As New Employee("John", "Thompson", "City Bank") Dim man As Manager = DirectCast(emp, Manager) Catch ex As InvalidCastException Console.WriteLine("Преобразование прошло неудачно") End Try
Третий способ заключается в проверке допустимости преобразования с помощью ключевого слова Is:
Dim emp As New Employee("John", "Thompson", "City Bank") If TypeOf emp Is Manager Then Dim man As Manager = DirectCast(emp, Manager) Else Console.WriteLine("Преобразование недопустимо") End If
Выражение TypeOf emp Is Manager
указывает, имеет ли переменная emp
тип Manager
. А поскольку
такая проверка вернет False, то преобразование не сработает. Для явного преобразования типов используется оператор DirectCast
,
который пытается преобразовать переменную emp к типу Manager.
Все сказанное выше в отношении преобразования типов характерно и для интерфейсов. Поскольку класс Client
реализует интерфейс
IAccount
, то переменная типа IAccount
может хранить ссылку на объект типа Client
:
Dim cl As IAccount = New Client("John", "Thompson", "City Bank", 200) cl.Put(200) Console.WriteLine("Остаток на счете : {0}", cl.CurentSum)