Иллюстрированный самоучитель по Visual Basic .NET

Снова о свойствах. Свойства и инкапсуляция.

Принципиальное различие в работе свойств VB6 и VB.NET заключается в том, что секции Get и Set теперь должны обладать одинаковым уровнем доступа. Определять свойства с секциями Public Get и Private Set в VB.NET не разрешается.

Примечание
Это ограничение легко обходится. Чтобы процедура Set фактически стала закрытой, объявите свойство с атрибутами Public Readonly и одновременно объявите другое, внутреннее закрытое свойство для Set
.

Кроме того, в VB6 свойство не могло изменяться в процедуре, даже если оно было передано по ссылке (то есть с ключевым словом ByRef). В VB.NET свойства, переданные по ссылке, могут изменяться.

Но самое принципиальное изменение относится к свойствам по умолчанию. В прежних версиях VB существовала концепция свойств по умолчанию, которая на первый взгляд казалась очень удобной. На практике свойства по умолчанию часто становились причиной ошибок в программах. Например, что означает следующая команда?

Me.Text1 = Text2

Отслеживая ошибки, возникающие в подобных командах, опытные пользователи VB выясняли, что эта команда задает свойству Text текстового поля с именем Text1 значение переменной Text2. Свойства по умолчанию не только становились источником ошибок в программах, но и требовали, чтобы при присваивании объектов использовалось ключевое слово Set, поскольку присваивание объектам нужно было отличать от присваивания свойствам. В VB.NET проблема свойств по умолчанию решается просто – они разрешены только там, где это действительно оправдано, а именно при использовании параметров.

Допустим, у вас имеется кэш-таблица aTable; при выборке значений было бы удобно использовать синтаксис вида aTable("theKey"), но это возможно лишь в том случае, если Item является свойством по умолчанию для класса HashTable. Свойства по умолчанию объявляются в классе с ключевым словом Default, причем это допускается лишь для свойств, получающих минимум один параметр. Если свойство по умолчанию перегружается, все перегруженные версии также помечаются ключевым словом Default. Свойства по умолчанию чаще всего используются в ситуации, когда у объекта имеется свойство, значение которого возвращается в виде массива или другого объекта, способного вмещать несколько величин (например, хэш-таблицы).

Предположим, у вас имеется класс Sales и свойство InYear, которое по полученному индексу возвращает число (объем продаж):

Public Class Sales
Private m_Sales() As
Decimal = {100, 200. 300}
Default Public Property InYear(ByVal theYear As Integer) As Decimal
Get
Return m_Sales(theYear)
End Get
Set(ByVa1 Value As Decimal)
m_Sales(theYear)=Value
End Set
End Property
' Остальной код класса End Class

Свойство по умолчанию позволяет использовать конструкции вида:

Dim ourSales As New Sales()
Console.WriteLine(ourSa1es(1))

Вместо:

Dim ourSales As New Sales()
Console.WriteLi ne(ourSales.InYear(1))

Или, например, вы можете написать:

ourSales (2) = 3000

Вместо:

ourSales.InYear(2) = 3000

Примечание
Ключевое слово Set используется в процедурах свойств VB NET
.

Свойства и инкапсуляция

На первый взгляд кажется, что свойства очень похожи на открытые поля экземпляров. Если объявить в классе А открытое поле с именем evil, на него можно сослаться при помощи конструкции A.evil; ничто не указывает на то, что свойство реализовано в виде открытой переменной. Может, определить открытое поле и избавиться от хлопот по определению процедур Get и Set?

Не поддавайтесь соблазну. Инкапсуляцию данных не стоит нарушать без веских причин (а еще лучше – не нарушать никогда!).

Но инкапсуляцию можно случайно нарушить и другими способами – например, если не следить за возвращаемыми значениями свойств. Каким образом? Если поле представляет собой изменяемый объект (например, массив), возвращение его в виде значения свойства приведет к нарушению инкапсуляции, поскольку внешний код сможет изменить состояние поля экземпляра через полученную объектную переменную. В таких ситуациях следует создать клон поля (клонирование объектов рассматривается в главе 5). Мораль:

Свойства не должны возвращать изменяемые объекты, которые представляют собой переменные классов.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.