1

Let's say I have an interface ITest1 defined:

Option Explicit

Sub it1Test(cTest As ITest1)
End Sub

And then I built a class CTest1 that implements it:

Option Explicit

Implements ITest1

Private Sub ITest1_it1Test(cTest As ITest1)
End Sub

Private Sub Test1()
    Dim cT1 As CTest1
    cT1 = New CTest1
    ITest1_it1Test cT1
End Sub

If I try compiling this code everything works perfectly fine, which in general is what I expect.

But then in my not so simple world, rather than passing a single element I want to pass a whole array.

So my new interface ITest2 looks like this

Option Explicit

Sub it2Test(cTest() As ITest2)
End Sub

And a class CTest2 implementing it:

Option Explicit

Implements ITest1

Private Sub ITest1_it1Test(cTest() As ITest1)
End Sub

Private Sub Test2()
    Dim cT2(1 To 1) As CTest2
    cT2(1) = New CTest2
    ITest2_it2Test cT2
End Sub

This time I am not able to compile with an error:

Compile error:

ByRef argument type mismatch

with highlighted the cT2 parameter of function ITest2_it2Test as the source of error.

Is there any way to pass an array of class implementing an interface if the function expects array of type of that interface. In other words does it make sense to use interface as a type of array parameter?

I'm aware that it is possible to use Variant as an array type but it undermines plenty of benefits that I have thanks to the use of interface.

I can't find anything related to such specific case. I have checked number of pages about ways to implement interfaces in general (from MS docs to CPearson page). I can't also find anything here on Stack Overflow. I have checked all 78 questions tagged vba and excel with keywords interface and array and some of the suggested questions.

Community
  • 1
  • 1
Ister
  • 5,958
  • 17
  • 26
  • Typed arrays are a PITA. Pass them as `Variant`, validate the parameter with `IsArray`, then validate that each element `Is ITest1`. Interface is a red herring, you'd get a "byref argument type mismatch" trying to pass a `String()` too. – Mathieu Guindon Nov 27 '18 at 19:40
  • Another alternative (arguably more idiomatic) would be to implement a custom collection class. You'll need a default `Item` property (getter with `VB_UserMemId=0` attribute), and a `NewEnum As IUnknown` property getter with `VB_UserMemId=-4` attribute. That property is easier to implement when your collection class is wrapping a `Collection` though: you can just return `internalCollection.[_NewEnum]`, a hidden property that returns exactly what you need there. – Mathieu Guindon Nov 27 '18 at 19:55
  • 1
    Thanks @MathieuGuindon . The funny part of the story is that I've built an interfaceish solution without using interfaces, entirely based on Variants. It worked nicely but in a normal programming language an interface helps maintain a nice, clean code etc... I was stupid enough to think that a language claiming to be object oriented but without class inheritance can reasonably handle interfaces and refactoring is a good idea. – Ister Nov 27 '18 at 20:30
  • Food for thought: C# is fully OOP and doesn't let you pass a `List` to a method that accepts a `List`. https://stackoverflow.com/q/6902157/1188513 – Mathieu Guindon Nov 28 '18 at 00:06

0 Answers0