Итак, в первой части мы затронули применение UDT в обычном модуле, и в комментариях справедливо заметили, что UDT сильно проигрывает классам. И да, действительно, если использовать класс как DTO (Data Transfer Object), он более функционален, чем UDT.
В этой заключительной части, я хотел бы рассказать о применении UDT в классах, кто такой Mathieu Guindon и причем тут резиновая уточка.
Ключевое слово this
Ну, на самом деле я слегка лукавлю, такого кейворда в VBA нет, но обо всем по порядку.
Обозначим задачу:
Мы разобрали, как использовать UDT в качестве структуры письма (см. первую часть). Это вполне себе рабочая схема, но иной раз не совсем удобная.
В чем же минусы? Сходу я вижу как минимум два:
Нет возможности встроить проверку передаваемых значений.
Чтобы собрать несколько UDT в один контейнер, в качестве этого самого контейнера можно использовать только массив. Это не то, чтобы критично, но часто неудобно.
А по сему, попробуем сделать реализацию структуры TLetter
в виде класса.
Создаем новый класс-модуль и называем его Letter
. Сразу пропишем необходимые поля:
Option Explicit
Public AddressTo As String
Public AddressCC As String
Public Subject As String
Так как это класс, надо бы пользоваться его функционалом.
Добавим проверку передаваемых значений, например email-адресов. Усложнять не будем, просто проверяем наличие символа "@" и бросаем ошибку, если его нет:
Option Explicit
Private AddressTo1 As String
Private AddressCC1 As String
Private Subject1 As String
Public Property Get AddressTo() As String
AddressTo = AddressTo1
End Property
Public Property Let AddressTo(ByVal RHS As String)
If Not ValidateEmail(RHS) Then Err.Raise 0, TypeName(Me)
AddressTo1 = RHS
End Property
Public Property Get AddressCC() As String
AddressCC = AddressCC1
End Property
Public Property Let AddressCC(ByVal RHS As String)
If Not ValidateEmail(RHS) Then Err.Raise 0, TypeName(Me)
AddressCC1 = RHS
End Property
Public Property Get Subject() As String
Subject = Subject1
End Property
Public Property Let Subject(ByVal RHS As String)
Subject1 = RHS
End Property
Private Function ValidateEmail(ByVal Email As String) As Boolean
ValidateEmail = InStr(1, RHS, "@") > 0
End Function
Что мы видим? Добавились свойства. У полей изменился модификатор доступа на private
и к каждому имени добавилась цифра 1.
Проблема в том, что VBA не чувствителен к регистру имен переменных, поэтому addressTo
и AddressTo
для него одно и тоже, а соответственно свойства и поля называть одинаково мы не можем.
И вот тут как нельзя кстати будет UDT
Объявляем новый тип TLetter
, помещаем в него все наши поля (с нормальными названиями, без цифр). Далее объявляем приватное поле this
с типом TLetter
.
Теперь переданное в свойство значение помещается в переменную вида this.AddressTo
, что выглядит куда лучше и понятнее:
Option Explicit
Private Type TLetter
AddressTo As String
AddressCC As String
Subject As String
End Type
Private this As TLetter
Public Property Get AddressTo() As String
AddressTo = this.AddressTo
End Property
Public Property Let AddressTo(ByVal RHS As String)
If Not ValidateEmail(RHS) Then Err.Raise 0, TypeName(Me)
this.AddressTo = RHS
End Property
Public Property Get AddressCC() As String
AddressCC = this.AddressCC
End Property
Public Property Let AddressCC(ByVal RHS As String)
If Not ValidateEmail(RHS) Then Err.Raise 0, TypeName(Me)
this.AddressCC = RHS
End Property
Public Property Get Subject() As String
Subject = this.Subject
End Property
Public Property Let Subject(ByVal RHS As String)
this.Subject = RHS
End Property
Private Function ValidateEmail(ByVal Email As String) As Boolean
ValidateEmail = InStr(1, RHS, "@") > 0
End Function
Mathieu Guindon и Rubberduck
Я думаю, вы наверняка уже видели подобное такое решение в моей первой статье на Хабре. По сути такой подход - есть ни что иное как паттерн. Автор этого паттерна господин Mathieu Guindon, он же автор достаточно известного дополнения для VBE - Rubberduck (резиновая уточка).
Так как в этой статье мы все таки разбираем UDT и способ его применения, а не то почему так правильнее делать, я бы хотел передать слово самому Mathieu, а именно его статье Private this As TSomething. В ней он достаточно подробно разбирает почему это удобно и чем плоха Венгерская нотация (а именно, добавление в название поля m
- mAddressTo
).
Короче...
Эта часть вышла более компактной, т.к. цель данной статьи не переписывать слова автора паттерна, а скорее обратить внимание на такой подход.
Надеюсь, что тем не менее было полезно.
Спасибо, что прочитали до конца.
Стали бы применять подобный паттерн? Пишите в комментариях!
А также, подписывайтесь на мой телеграмм.