3

Disclaimer: I have a bit of experience with PHP, Java and VBA but I am mainly a front end developer so Javascript is more my thing.

I am trying to create some classes which implement an Interface in an MS Access Database and I can't even get the concept to work.

What I have:

IFeed Class (the interface)

Option Explicit
Public Name As String

Public Property Get Name() As String
End Property

Public Property Let Name(ByVal vNewValue As String)
End Property

CFeed Class

Option Explicit

Implements IFeed

Private Name As String

Private Property Let IFeed_Name(ByVal newName As String)
    Name = newName
End Property

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

Test module

Public Sub testFeedClass()
    Dim test As CFeed
    Set test = New CFeed
    test.Name = "New Feed" ' Doesn't work
    Debug.Print test.Name
End Sub

I have spend almost a day changing private to public, public to private and loads of other things but I just can't get it to work. Can someone please point out where I am going wrong? I am sure it is something simple.

punkrockbuddyholly
  • 9,675
  • 7
  • 36
  • 69
  • 1
    See if [this answer](http://stackoverflow.com/a/19908375/2144390) helps. – Gord Thompson Feb 11 '15 at 10:52
  • That was the first answer I found when I began researching this problem. Unfortunately when I do it this way I get the error `Object module needs to implement '~' for the interface '~'` and when I google for that it seems no one else in the world has seen this error. – punkrockbuddyholly Feb 11 '15 at 10:58
  • @MrMisterMan That is probably because the code you showed is not exactly the code you have. The code you show will not compile because the interface has both a field named `Name` and a property named `Name`, so that is `Ambiguous name detected: Name`. If you rename the field, the error will be `Object module needs to implement 'Name1' for interface 'IFeed'`. That is because you need to implement the field in `CFeed` as well (will actually be implemented as a property). The correct thing to do is to remove the field from the interface altogether, or to convert it to a property. – GSerg Feb 11 '15 at 11:19
  • @GordThompson if I do it exactly as shown in that answer I get the compile error `Object module needs to implement 'Name' for interface 'IFeed'`. But I have the property setter and getter for Name in both my interface _and_ CFeed class. – punkrockbuddyholly Feb 11 '15 at 11:51
  • @MrMisterMan What you actually have is probably not what you think you have. If in the `CFeed` code module you select `IFeed` from the left dropdown, do you have any unimplemented (non-bold) properties in the right dropdown? – GSerg Feb 11 '15 at 12:03

1 Answers1

3

In VBA members of implemented interfaces do not make it into the class object itself, like e.g. they do in C#'s implicit interface implementation.

To use the implemented interface, you need to cast the object to that interface:

Dim test As IFeed
Set test = New CFeed
test.Name = "New Feed"
Community
  • 1
  • 1
GSerg
  • 76,472
  • 17
  • 159
  • 346
  • Thank you, this is working. However I have seen examples where this isn't the case so it looks like I should be able to do `Dim test As CFeed`. For example the answer which @Gord linked to in his comment on my answer does not Dim the variable as the interface. So I still don't quite understand it. – punkrockbuddyholly Feb 11 '15 at 11:41
  • 1
    @MrMisterMan In that answer the object is declared as itself because in the object's code they duplicate all properties of the implemented interface, mapping them to the actual implemented properties. So you'd have to have `Private Property Let IFeed_Name`, `Private Property Get IFeed_Name`, `Public Property Let Name` and `Public Property Get Name` in `CFeed`, where the latter two return the values of the former two. As the number of properties grow, maintaining this manual mapping becomes annoying. – GSerg Feb 11 '15 at 11:58