I am reading up on creating class factories here: https://rubberduckvba.wordpress.com/2018/04/24/factories-parameterized-object-initialization/ and I am confused why they are making the implemented functions private, wouldn't we want them to be public so we can access them?
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "Something"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
Private Type TSomething
Bar As Long
Ducky As String
End Type
Private this As TSomething
Implements ISomething
Public Function Create(ByVal initialBar As Long, ByVal initialDucky As String) As ISomething
With New Something
.Bar = initialBar
.Ducky = initialDucky
Set Create = .Self
End With
End Function
Public Property Get Self() As ISomething
Set Self = Me
End Property
Public Property Get Bar() As Long
Bar = this.Bar
End Property
Friend Property Let Bar(ByVal value As Long)
this.Bar = value
End Property
Public Property Get Ducky() As String
Ducky = this.Ducky
End Property
Friend Property Let Ducky(ByVal value As String)
this.Ducky = value
End Property
Private Property Get ISomething_Bar() As Long
ISomething_Bar = Bar
End Property
Private Property Get ISomething_Ducky() As String
ISomething_Ducky = Ducky
End Property
Also, why do you need to provide get and let properties for public variables in an interface?
They should be Private.
The reason is because how interfaces work in VBA: the Public members of a class module define its default interface. That means the public members of Class1 define what members Class2 must implement if it Implements Class1.
So if you make Class1_DoSomething public, then you're exposing that member on the default interface of Class2, and that's... not pretty at all.
What interface you access an object with, is determined by how you declare it.
Dim thing As Class1
Set thing = New Class1
If thing is or implements Class1, then the code after this declaration can invoke all the members exposed by the default interface of Class1 (i.e. its public members).
If Class1 implements ISomething and we declare it like this:
Dim thing As ISomething
Set thing = New Class1
Now the members we get to work with are the members defined by the public members of the ISomething class/interface.
When you implement an interface or handle events, you should never manually type the signatures; instead, pick the interface (or event provider) from the upper-left dropdown in the code pane, then pick a member from the upper-right dropdown: the VBE automatically creates the correct procedure with the correct signature, and it's always going to be a Private member - rule of thumb, anything that has an underscore in its name in VBA has no business being Public
As for why you must supply Get and Let accessors for what you defined as a public field (/variable) on an interface class... Fields are implementation details, they should never be Public in the first place. Objects expose properties, not fields - keep fields for the private internal state of the implementing class.
The reason is technical: VBA code gets compiled into a COM type library, and that library sees your public variable and says "that's going to have to be a PUT and a GET method", and the VBA code implementing that interface thus needs to implement a property for every public field, because public fields compile down to properties.
This does have interesting implications with regards to the practice of exposing a public field on a class module (breaks encapsulation vs compiles down to a property anyway!), but that is a whole other discussion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With