Практическое использование вложенных классов на примере связанного списка
Вложенные классы чаще всего применяются в реализациях различных структур данных. К числу самых распространенных структур данных принадлежит связанный список. Он представляет собой цепочку ссылок, которая позволяет легко переходить от текущего объекта к следующему, однако поиск всегда начинается с конкретной ссылки. Применение вложенных классов в реализации связанного списка выглядит вполне естественно, поскольку код объектов-ссылок не представляет интереса для пользователей класса LinkedList, а объекты Link не могут существовать независимо от содержащего их объекта LinkedList.
Ниже приведена очень простая реализация класса для работы со связанными списками. Просмотрите ее, а затем мы подробно проанализируем листинг. Обратите внимание на важную строку, выделенную жирным шрифтом (строка 49); в ней используется нетривиальная особенность объектно-ориентированного программирования, о которой будет рассказано ниже.
1 Option Strict On
2 Module Modulel 3 Sub Main()
4 Dim aLinkedList As New LinkedlistC'first link")
5 Dim aALink As LinkedList.Link
6 aLink = aLinkedList.MakeLink(aLinkedList.GetFirstLink,"second link")
7 aLink = aLinkedList.MakeLink(aLink,"third link")
8 Console.WriteLine(aLinkedList.GetFirstLink.MyData)
9 aLink = aLinkedList.GetNextLink(aLinkedList.GetFirstLink)
10 Console.WriteLine(aLink.MyData)
11 Console.WriteLine(aLink.NextLink.MyData)
12 Console. ReadLine()
13 End Sub
14 Public Class LinkedList
15 Private m_CurrentLink As Link
16 Private m_FirstLink As Link
17 Sub New(ByVal theData As String)
18 m_CurrentLink = New Link(theData)
19 m_FirstLink = in_CurrentLink
20 End Sub
21 Public Function MakeLink(ByVal currentLink As Link.ByVal
22 theData As String) As Link
23 m_CurrentLink =New Link(currentLink.theData)
24 Return m_CurrentLink
25 End Function
26 Public Readonly Property GetNextLink(ByVal aLink As Link)_
27 As Link
28 Get
29 Return aLink.NextLink()
30 End Get
31 End Property
32 Public Readonly Property GetCurrentLink()As Link
33 Get
34 Return m_CurrentLink
35 End Get
36 End Property
37 Public Readonly Property GetFirstUnkOAs Link
38 Get
39 Return m_FirstLink
40 End Get
41 End Property
42
43 ' Вложенный класс для ссылок
44 Friend Class Link
45 Private m_MyData As String
46 Private m_NextLink As Link
47 Friend Sub New(ByVal myParent As Link.ByVal theData As String)
48 m_MyData - theData
49 myParent.m_NextLink = Me
50 ' End Sub
51 Friend Sub New(ByVal theData As String)
52 m_MyData =theData
53 End Sub
54 Friend Readonly Property MyData()As String
55 Get
56 Return m_MyData
57 End Get
58 End Property
59 Friend Readonly Property NextLink()As Link
60 Get
61 Return m_NextLink
62 End Get
63 End Property
64 End Class
65 End Class
66 End Module
Строка 4 создает новый экземпляр связанного списка. В строке 5 определяется объектная переменная типа Link. Поскольку класс Link является вложенным по отношению к LinkedList, его тип записывается в виде «полного имени» LinkedList.Link. Строки 6-12 содержат небольшую тестовую программу.
В строках 17-20 определяется конструктор класса LinkedList, в котором вызывается второй конструктор класса Link (строки 51-53). Последний объявлен с атрибутом Friend и потому доступен для внешнего класса Li nkedLi st. Если бы конструктор Link был объявлен с атрибутом Private, то он стал б"ы недоступным для внешнего класса.
Также стоит обратить внимание на то, как в первом конструкторе класса Link (строки 47-50) организуется ссылка на только что созданный элемент списка из предыдущего элемента. Для этого используется ключевое слово Me — это очень принципиальный момент, поэтому строка 49 выделена в листинге жирным шрифтом. На первый взгляд команда myParent.m_NextLink = Me выглядит недопустимой, поскольку мы обращаемся к закрытому полю родительского класса myParent. Однако программа все-таки работает! Итак, запомните очень важное правило:
Для экземпляра класса всегда доступны закрытые поля других экземпляров этого класса.