Вложенные классы. Практическое использование вложенных классов на примере связанного списка.
В программах VB.NET нередко встречаются ситуации, когда у вас имеются два класса: "внешний" и "внутренний", фактически принадлежащий первому. Вложенные (nested) классы обычно выполняют вспомогательные функции, и их код имеет смысл лишь в контексте внешнего класса. Существует хорошее эмпирическое правило: если при просмотре внешнего класса код вложенного класса можно свернуть в окне программы и это не затруднит понимания логики внешнего класса, значит, работа вложенного класса организована правильно.
Конечно, использование вложенных классов всегда приводит к некоторому нарушению инкапсуляции – вложенный класс может обращаться к закрытым членам внешнего класса (но не наоборот!). Если это обстоятельство учитывается в архитектуре вашего приложения, не стоит уделять ему особого внимания, поскольку внутренний класс всего лишь является специализированным членом внешнего класса.
Примечание
VB.NET не позволяет расширять область видимости вложенного класса посредством функций. Например, открытый член внешнего класса не может вернуть экземпляр закрытого или дружественного (Friend) вложенного класса.
Вложенные классы чаще всего применяются в реализациях различных структур данных. К числу самых распространенных структур данных принадлежит связанный список. Он представляет собой цепочку ссылок, которая позволяет легко переходить от текущего объекта к следующему, однако поиск всегда начинается с конкретной ссылки. Применение вложенных классов в реализации связанного списка выглядит вполне естественно, поскольку код объектов-ссылок не представляет интереса для пользователей класса 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