How to use comparison methods between class object modules in VBA in a similar manner as VB.NET?
Asked Answered
L

1

24

Due to new project in VBA I moved from VB.NET, to be honest don't really know how to deal between objects classes here. What I want to reach is comparing objects between different class object modules.

e.g

class Employee
     properties: Name, Age
     point is: compare Names between two Employees

classes: Employee and Manager
point is: compare Name from Employee with Name of Manager

I know how to in VB.NET, but how do I compare properties of different class module objects in VBA?

Lippert answered 9/11, 2013 at 19:5 Comment(0)
S
82

VBA doesn't support class polymorphism so I recommend to change the way you're thinking about the Employee and Manager classes.

You can't have an Employee class as a base class and then a separate Manager class that derives from Employee. They could be 2 separate classes implementing a common interface.

I will talk about it in detail in a bit. Let's now go through a few examples...


↓ Easy approach ↓


A base class (Person) and child classes which derive from the base class. (applies to C#, VB.NET, etc)

but in VBA you have to think of it like this:

A base class which exposes an enum property describing the position.

Something like

enter image description here

enter image description here

This is the easiest way to have a class exposing some properties. It allows you to add your Person objects into a collection and iterate over using the easy for each loop with Intellisense!

enter image description here

Properties comparison system would be very very easy

enter image description here

note: same applies to enum as its implicitly converted to a number


↓ More complex approach ↓


Two separate classes which both expose public properties. For instance you have an Employee and Manager classes which both implement a Person Interface and an additional Comparer class exposing a Compare() method

enter image description here

In your VBA Project you need 4 class modules and a standard module

enter image description here

Person (this is your Interface)

Public Property Get Name() As String
End Property

Public Property Get Age() As Long
End Property

this class is the interface which both the Employee and Manager both need to implement to share some common functions (getters for Names and Ages). Having the interface allows you to do the for each loop using the interface type variable as the enumerator. You will see in a minute.

Employee and Manager are identical. Obviously you may modify them to suit your real life solution.

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 you will use an instance of this class to compare two objects properties or references. You do not necessarily need to have a class for this but I prefer it that way.

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

And your Module1 code

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

run the Main() sub and check out the results in the Immediate Window

enter image description here

The best part of the above code is the fact that you are creating a reference variable of the Person interface. It allows you to loop through all items in the collection that implement the interface. Also, you can use the Intellisense which is great if you have had many more properties and functions.


Comparison


Take a look again at the code in the ComparerCls class

enter image description here

I hope you see now why I have separated this to be a class. Its purpose is just to take care of the way the objects are being compared. You can specify the Enum order and modify the Compare() method itself to compare differently. Note the Optional parameter which allows you to call the Compare method without the method of comparison.

enter image description here

Now you can play around passing different parameters to the compare function. See what the results are like.

Try combinations:

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

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

Comparer.Compare(emp, emp, References)

If something is still unclear refer to this answer about the Implements keyword in VBA

Substantive answered 11/11, 2013 at 14:9 Comment(7)
great example thx for your time and contribute. But two questin due to that. As i can see the Person is an interface and other classes can implement that, but Person is actually the CLASS too and other classes implements from it in this case Manager and Employee in the example ( two properties) instead of properties could it be also methods? Second if possible Manager class can implement Person (class) interface why let's say Manager can't implement Employee's methods and fields as they are the same as Person?Lippert
@StackUser well, yes see this for an example of how other classes implementing interfaces need to provide implementation of methods. I think the answer for the second question lies in the first few sentences of my answer. VBA does not support class polymorphism that's why one class can't derive from another.Substantive
@StackUser if something is still unclear then maybe read this answer too :)Substantive
+1 awesome answer! very useful! didn't know we can use interfaces in VBA!Laris
Great Answer. What I do not understand are the private "Person_Name" and "Person_Age" properties of the Employee and Manager Classes. Are they used anywhere?Ventail
@Ventail Person is an interface that both classes (Manager and Employee) implement. By implementing an interface you (as the developer implementing it) need to guarantee that your classes provide the body for any properties and methods declared in the interface. Any real person has a name and age therefore any classes further "derived" ( like Person's children ) also will need to have a name and age. Look up Polymorphism if you want to better understand OOP.Substantive
Awesome answer. I wish there were more like this.Herstein

© 2022 - 2024 — McMap. All rights reserved.