
Итак, в первой части мы затронули применение 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).
Короче...
Эта часть вышла более компактной, т.к. цель данной статьи не переписывать слова автора паттерна, а скорее обратить внимание на такой подход.
Надеюсь, что тем не менее было полезно.
Спасибо, что прочитали до конца.
Стали бы применять подобный паттерн? Пишите в комментариях!
А также, подписывайтесь на мой телеграмм.