Overloading and Optional Parameters

I have a class with overloaded Constructors:

They’re all different:

  • Integer, String, Optional Variant
  • Integer, String, String, Optional Variant
  • Integer, String, Integer, String, Optional Variant
  • String

When I try to call the constructor with Integer, String, Variant, I get

There is more than one method with this name but this does not match any of the available signatures.
Packet = New APIpacket(FrameType_ATcommand,Parameter,Value)

Is the compiler not smart enough to differentiate signatures when optional parameters are involved? Even if I removed the optional parameter or made it non-optional, they’d all be unique.

I’ve see this before.

As a variant can be anything the compiler can’t distinguish between teh versions because of the optional variant which does not have to be there. The conversation of variant to specific type must be happening too soon.

-Karen

But like I said, even if the last parameter was to be removed from all the signatures, they’d still all be unique.

Making all the parameters non-optional solves the problem (but makes the calling code uglier).

One of the parameter passed is of type Boolean, and none of the signatures have a Boolean parameter. I know that the error message does not tell that no signature is matched, but could it be that the wrong message is displayed ?

No, the Boolean shown is being passed to the Set method, but the error is in the call to the constructor of the APIpacket class, which is being passed an integer, a string, and a variant, matching the signature of the first constructor shown.

IMHO, I wouldn’t recommend overload constructors or methods come to that. Instead I would recommend using shared factory functions which allows the function name to provide hints about what parameters or what purposes that particular function does/aids/resolves.

myClass.createWithFrameType( integer, string, optionalVariant )
myClass.createWithDestMAC( integer, string, string, optionalVariant )
myClass.createWithFlorLinkCommand( Integer, String, Integer, String, optionalVariant )
myClass.createWithPacketType( string )
5 Likes

Good suggestion, @Sam_Rowlands . I thought I was being all clever and OOPsy with my overloaded constructors, but your idea is probably clearer. The downside is that it would take one call to instantiate and another to “create”.

1 Like

No, although he didn’t show it, these functions would return an instance.

1 Like

So you can call a shared method on a class without having an instance? And that method uses New to make an instance?

1 Like

Yes, shared methods and functions do not require an instance.

2 Likes

Always more to learn :slight_smile:

1 Like

So yeah, pretty nifty, and not a lot of work to change things around per @Sam_Rowlands shared factory methods suggestion. It makes the instantiation calls a little less verbose (one less parameter) and a little more obvious in their intent. One issue is that the factory methods need to use some methods that are currently instance methods. Is it considered better practice to leave them as instance methods and call them on the new instance that’s being created, e.g.

Dim packet as new APIpacket
packetstring = packetstring + packet.checksum(packetstring)

or to just make all such methods (i.e. checksum) shared methods?

1 Like

If it doesn’t require an instance, make it shared.

2 Likes

Sorry for not making that clear.

Thanks @Kem_Tekinay for filling in the gaps.

1 Like

One more thing: shared methods can access any properties or methods of an instance, including ones marked private, so with the “factory” technique, you can:

  • Add a single Constructor and make it private.
  • Have the “Create” factory methods fill in the private properties of the instance, or call private init methods, as needed.

This will keep outside code from using “New” to create an instance of your class, and will simplify the Constructor coding.

2 Likes

That’s exactly what I’ve done :slight_smile:

3 Likes

I think that you are looking for something like what I do for dialogs:

Shared Sub ShowDialog(Title As string, Prompt As String)
 Dim win As New wWindowName  'win is a INSTANCE
 win.init (Title, Prompt)
 win.ShowModal
 Return win.Status 'In here I return a property but you can return the instance itself
End Sub
NOT_Shared Private Sub init(Title As string, Prompt As String)
self.title = Title
lblPrompt.text =Prompt
End Sub
NOT_Shared Event ButtonGuardarAction
 Self.Status= txtboxstatus.text
 Self.close
End Sub

And you can have more shared subs:

Shared Sub ShowDlg(Prompt As String)
 Dim win As New wWindowName  'win is a INSTANCE
 win.init ("A fixed title", Prompt)
 win.ShowModal
 Return win.Status 'In here I return a property but you can return the instance itself
End Sub

You can avoid the constructor and simply have a private initialization function that you call with any combination of parameters you like

Yes, I get it now. I’ve known about shared methods and read about the factory pattern, but it was all kind of abstract and I never saw the use case until @Sam_Rowlands and @Kem_Tekinay pointed out to me that my current application is the use case. I think the big “light bulb” moment for me was the realization that you don’t need an instance to call a class method. Having implemented the pattern once now with a real application, it all makes total sense.

3 Likes