Как использовать методы сравнения между объектными модулями класса в VBA аналогично VB.NET?

19

Из-за нового проекта в VBA я перешел с VB.NET, честно говоря, не знаю, как справляться между классами объектов здесь. То, что я хочу достичь, - это сравнение объектов между различными объектными модулями класса.

например

Сотрудник класса
      свойства: Name, Age
      точка: сравнить Name между двумя сотрудниками

классы: Сотрудник и Менеджер
точка: сравнить Name с Сотрудник с Name Менеджера

Я знаю, как это сделать в VB.NET, но как сравнить свойства разных объектов модуля класса в VBA?

Теги:
class
interface
comparison

1 ответ

59
Лучший ответ

VBA не поддерживает классовый полиморфизм, поэтому я рекомендую изменить то, как вы думаете о классах Employee и Manager.

Вы не можете иметь класс Employee в качестве базового класса, а затем отдельный класс Manager, который выводит из Employee. Они могут быть 2 отдельными классами, реализующими общий интерфейс.

Я расскажу об этом подробно. Теперь давайте рассмотрим несколько примеров...


↓ Простой подход ↓


A base class (Person) и дочерние классы, которые происходят из базового класса. (относится к С#, VB.NET и т.д.)

но в VBA вы должны думать об этом так:

Базовый класс, который предоставляет свойство enum, описывающее позицию.

Что-то вроде

Изображение 3821

Изображение 3822

Это самый простой способ иметь класс, отображающий некоторые свойства. Он позволяет добавлять объекты Person в коллекцию и перебирать их с помощью простого цикла for each с Intellisense!

Изображение 3823

Система сравнения свойств будет очень проста

Изображение 3824

note: то же самое относится к перечислению как его неявно преобразованное в число


↓ Более сложный подход ↓


Два отдельных класса, которые отображают публичные свойства. Например, у вас есть классы Employee и Manager, которые реализуют Person Интерфейс и дополнительный класс Comparer, подвергая метод Compare()

Изображение 3825

В вашем проекте VBA вам нужны 4 модуля классов и стандартный модуль

Изображение 3826

Person (это ваш интерфейс)

Public Property Get Name() As String
End Property

Public Property Get Age() As Long
End Property

этот класс является интерфейсом, который оба типа Employee и Manager должны реализовать, чтобы совместно использовать некоторые общие функции (геттеры для имен и возрастов). Наличие интерфейса позволяет вам выполнять для каждого цикла использование переменной типа интерфейса в качестве счетчика. Вы увидите через минуту.

Employee и Manager идентичны. Очевидно, вы можете изменить их в соответствии с вашим решением в реальной жизни.

Implements Person

Private name_ As String
Private age_ As Long

Public Property Get Name() As String
    Name = name_
End Property

Public Property Let Name(ByVal Value As String)
    name_ = Value
End Property

Public Property Get Age() As Long
    Age = age_
End Property

Public Property Let Age(ByVal Value As Long)
    age_ = Value
End Property

Private Property Get Person_Name() As String
    Person_Name = Name
End Property

Private Property Get Person_Age() As Long
    Person_Age = Age
End Property

ComparerCls вы будете использовать экземпляр этого класса для сравнения двух свойств или ссылок объектов. Для этого вам необязательно иметь класс, но я предпочитаю его таким образом.

Public Enum ComparisonMethod
    Names = 0 ' default
    Ages = 1
    References = 2
End Enum

' makes names the default comparison method
Public Function Compare(ByRef obj1 As Person, _
                        ByRef obj2 As Person, _
                        Optional method As ComparisonMethod = 0) _
                        As Boolean

    Select Case method
        Case Ages
            Compare = IIf(obj1.Age = obj2.Age, True, False)
        Case References
            Compare = IIf(obj1 Is obj2, True, False)
        Case Else
            Compare = IIf(obj1.Name = obj2.Name, True, False)
    End Select

End Function

И ваш Module1 код

Option Explicit

Sub Main()

    Dim emp As New Employee
    emp.Name = "person"
    emp.Age = 25

    Dim man As New Manager
    man.Name = "manager"
    man.Age = 25

    Dim People As New Collection
    People.Add emp
    People.Add man

    Dim individual As Person
    For Each individual In People
        Debug.Print TypeName(individual), individual.Name, individual.Age
    Next

End Sub

запустите подкомпоновку Main() и проверьте результаты в окне немедленного просмотра

Изображение 3827

Лучшая часть приведенного выше кода заключается в том, что вы создаете ссылочную переменную интерфейса Person. Он позволяет прокручивать все элементы коллекции, которые реализуют интерфейс. Кроме того, вы можете использовать Intellisense, что отлично, если у вас было много других свойств и функций.


Сравнение


Посмотрите еще раз на код класса ComparerCls

Изображение 3828

Надеюсь, теперь вы видите, почему я разделил это как класс. Его цель - просто позаботиться о том, как сравниваются объекты. Вы можете указать порядок Enum и изменить метод Compare() для сравнения по-разному. Обратите внимание на необязательный параметр, который позволяет вам вызвать метод сравнения без метода сравнения.

Изображение 3829

Теперь вы можете играть вокруг передачи различных параметров функции сравнения. Посмотрите, как выглядят результаты.

Попробуйте комбинации:

emp.Name = "name"
man.Name = "name"

Comparer.Compare(emp, name, Names)
Comparer.Compare(emp, name, References)

Comparer.Compare(emp, emp, References)

Если что-то еще неясно, обратитесь к этому ответу о ключевом слове Implements в VBA

  • 1
    Отличный пример, спасибо за ваше время и вклад. Но два квеста из-за этого. Как я вижу, Person - это интерфейс, и другие классы могут реализовать это, но Person на самом деле тоже CLASS, и другие классы реализуют его в этом случае Manager и Employee в примере (два свойства) вместо свойств могут быть также методами ? Во-вторых, если это возможно, класс Manager может реализовывать интерфейс Person (класса), почему, скажем, Manager не может реализовать методы и поля Employee, поскольку они совпадают с Person?
  • 1
    @StackUser хорошо, да видеть это на примере того , как другие классы , реализующие интерфейсы должны обеспечивать реализацию методов. Я думаю, что ответ на второй вопрос заключается в первых нескольких предложениях моего ответа. VBA не поддерживает полиморфизм классов, поэтому один класс не может быть производным от другого.
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню