Ранее мы уже говорили о преобразовании простейших типов. Теперь затронем тему преобразования объектов различных классов. Итак, у нас есть следующая система классов:
'Классы
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)