Wednesday, 10 January 2018

VBA - Difference between Friend and Public with inter project references.

A question has come up on SO about wanting to restrict the visibility of some methods to one set of classes. This is doable with the Friend keyword instead of using the Public but requires splitting your code into separate projects and this brings its own issues with it such as denoting a class as not creatable and shipping a factory function. So an example is not brief. I give instructions here as to see how the Friend keyword works. You will need two Excel workbooks at minimum.

  1. Create first workbook, change its project name to MyServer and then save that workbook to disc.
  2. Create second workbook and using Tools->References make a reference to MyServer, this sets up the inter workbook reference.
  3. In the first workbook add the FriendClass class module (see code below) and change its instancing to PublicNotCreatable
  4. In the first workbook add the PublicClass class module (see code below) and change its instancing to PublicNotCreatable
  5. In the first workbook add the modServerSideTest standard module (see code below). Run the procedure TestServerSideTest (using F5) to test it is correct.
  6. In the first workbook add the modFactoryFunctions standard module (see code below).
  7. In the second workbook add the modClientSideTest standard module (see code below).
  8. In the second workbook, modClientSideTest standard module, run the procedure TestClientSide (using F5) to test the cross workbook class creation
  9. To demonstrate how the Friend keyword hides a method un-comment the line Debug.Print oFriend.FriendlyGreeting and witness compile error

The FriendClass class module


Option Explicit

'* The FriendClass

Friend Function FriendlyGreeting() As String
    FriendlyGreeting = "Whasssup!!"
End Function

Public Function PublicGreeting() As String
    PublicGreeting = "Good morning, friend."
End Function

The PublicClass class module


Option Explicit

'* The PublicClass

Public Function PublicGreeting() As String
    PublicGreeting = "Good morning to you, sir."
End Function

The modServerSideTest standard module


Option Explicit

'* modServerSideTest

Sub TestServerSideTest()

    Dim oFriend As FriendClass
    Set oFriend = New FriendClass
    
    Debug.Print oFriend.FriendlyGreeting
    
    Dim oPublic As PublicClass
    Set oPublic = New PublicClass

    Debug.Print oPublic.PublicGreeting


End Sub

The modFactoryFunctions standard module


Option Explicit

'* modFactoryFunctions

Public Function CreateInstanceFriendClass() As FriendClass
    Set CreateInstanceFriendClass = New FriendClass
End Function

Public Function CreateInstancePublicClass() As PublicClass
    Set CreateInstancePublicClass = New PublicClass
End Function

The modClientSideTest standard module


Option Explicit

'* modClientSideTest

Sub TestClientSide()

    Dim oFriend As MyServer.FriendClass
    Set oFriend = MyServer.CreateInstanceFriendClass
    
    'Debug.Print oFriend.FriendlyGreeting '*not reachable, does not compile, that achieves the goal of Friend
    Debug.Print oFriend.PublicGreeting
    
    Dim oPublic As MyServer.PublicClass
    Set oPublic = MyServer.CreateInstancePublicClass

    Debug.Print oPublic.PublicGreeting
End Sub

No comments:

Post a Comment