Pull to refresh

User Defined Type. Что это и как его использовать, часть 2

Level of difficultyEasy
Reading time3 min
Views1.6K
Source: https://www.meme-arsenal.com/create/meme/1067402
Source: https://www.meme-arsenal.com/create/meme/1067402

Итак, в первой части мы затронули применение 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).

Короче...

Эта часть вышла более компактной, т.к. цель данной статьи не переписывать слова автора паттерна, а скорее обратить внимание на такой подход.

Надеюсь, что тем не менее было полезно.

Спасибо, что прочитали до конца.
Стали бы применять подобный паттерн? Пишите в комментариях!
А также, подписывайтесь на мой
телеграмм.

Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
Total votes 1: ↑1 and ↓0+1
Comments0

Articles