Let’s do some multiverse madness here and do something specific but do it across different programming languages! 🙂
For this one, let’s make the class or rather the instance of it — callable; that is, instead of the client invoking its method, we invoke itself.
What do I mean by this?
Most of us call class methods to perform an action, but we usually don’t call the class instance itself. I guess the best way to explain is via a sample code.
So instead of this:
result = class_instance.method(param)
The code is this:
result = class_instance(param)
Python
In Python, it’s super simple. We just override a dunder method to do it. That dunder method is “__call__”. Here’s a super simple example:
Visual Basic dot NET
Now, let’s implement the same functionality or behavior using the newer incarnation of Visual Basic.
VB.Net provides the “Default” keyword and it works for our demo, but unfortunately it can only be used on properties (not methods). Here’s the equivalent code in VB.Net:
Visual Basic 6.0
You probably didn’t expect to see this, or even think it’s possible in VB6, but it is and very, very few people know of this 🙂
I’ve used this feature a very long time ago (probably early 2000s), but during that period, there wasn’t much use case to do it and so I really didn’t use it much.
But for this demo, I’ll show you how you can implement the same thing in VB6.
As usual, create you class and then define a method that you’d want to be its default behavior. In our example, the method we want to make default is “greet”.
Now, go to “Tools” and then “Procedure Attributes” while the class is the active window.
The Procedure Attributes dialog window will pop up. From the “Name” selection, make sure that “greet” is selected (in case you have more than one method). Then click “Advanced” which will expand the dialog window and show more options.
From the new options, go to “Procedure ID” and select “(Default)” then finally click “OK” to apply the changes.
Once you’ve done that, try calling the class instance. For this demo, I didn’t use any form, just the Basic Module to test it.
As per usual, we create an instance of the class and then proceed to use it as if it’s a function (or method):
Why and when do I use this?
Yeah, you can just call a regular method call which is much clearer in terms of intent so why would you even want to do this? Or when would you even consider using it?
For Prototyping
If you’re building an application or a system, most of it are unclear or is not set. Say you need a method to calculate a salary.
You proceeded to create a “calculate” method and released your library/module. The accounting IT team started using it into their modules and things are doing great.
After 2 weeks, the boss said that the Tax IT department is using “calculate” method so you have to change it to “calculate_salary” so that it’s not the same as the Tax ITs method name. Well, what happens when you do this and release the update? All the clients using your library won’t work anymore since there’ll be no more “calculate” method.
By making the class callable, this won’t break the client code since you’ll just be changing the default behavior from one method to another, which is completely transparent to the clients.
For Creating Framework
Frameworks are hard to do. You really have to establish a standard cause you can’t keep on changing them once you release it.
And similar to the scenario described in prototyping, things typically change and the least you could do is ensure that those changes have minimal to zero impact on production.
If your framework expects an object to have a “execute” method, then all the object creators can never use that method name anymore to do something else or that if there’s a method collision discovered later on, it’d be hard to fix. Making the class instance callable addresses this and lets the object creators change which method gets called without breaking your framework.
For Special Cases
There’s probably something you could think of that this would come in handy or maybe the best solution to a specific problem. This is probably the reason you don’t see this implemented very often, and maybe not even known, because the use case is limited. However, it’s worth knowing that this option exists and that you can pull it out of your bag of tricks when you do need it.
PL Versions and Source Codes
Here are the programming language versions used in this blog:
- Python 3.7.4
- Visual Studio 2017 Community Edition
- Visual Basic 6.0
The source codes are in the Git repository below:
https://github.com/vegitz/codes/tree/master/0026%20Callable%20Classes