09-07-2026 01:35 AM
I have a base class and two children classes. The base class defines a Create() method which is set to "Descendants must override". In my implementation it doesn't make any sense for the user to directly call the base class Create(), he always should call a child implementation.
So I thought I just set the base class method private, but this does not work for whatever labview implementation reasons. How can I enforce a broken VI if the user accidentally wants to use the base class method? (I was thinking about making the base class implementation broken on purpose, but I think this would be a really poor programming solution not to mention that in certain cases the child class may want to call the parent class method)
I used dynamic dispatch for the overriding VIs.
Thanks.
09-07-2026 02:50 AM
Yes, this is a very poor solution.
Consider also that you cannot have overwridden methods with different scopes (public, protected). Moreover, dynamic dispatch methods cannot be private. They cannot be private because there'd be no way to override them.
Anyway, I see 2 ways to address your issue:
Create().Create() method of the base class should return an error (i.e. 'Not supported error'). In this way, you intercept and handle the error.Bonus option (although I cannot know whether it fits your architecture):
You could remove the Create() method from the base class and instead define a static Create() method in each child class, making that method responsible for instantiating its corresponding class.
Create() methods, and, more importantly, your code will only instantiate a child class through the child class's own Create() method.09-07-2026 03:41 AM
Thanks. One drawback of not having a Create() method in the parent class (or outputing an error) is that child classes can't reuse it if its appropriate. This in theory could mean that many child classes need to implement the same Create() function. But as far as I see there is no way out of this in LabVIEW. (maybe an intermediate class, but eh... that also could have issues)
I control the architecture that's true. But when I said "user" I really meant other programmers who will work with these classes in the future.
But all these are a rather low risk / low probability events in our environment, so even if I keep everything unchanged it will most likely work. Its a bit odd though to learn about these limitations of LV. I thought this stuff is pretty much there for every oop languages. But thats fine, LV must have its own legit reasons for implementing classes like this.
09-07-2026 04:10 AM
You still have control even when you it comes to share code with other developer.
You should rely on method scope (private, protected, public) and on the distinction between static and dynamic dispatch. With these two mechanisms, you can expose only the specific functionality you want developers to access.
If you need to make the Create() method reusable, consider introducing a separate method (Init(), Initialize(), DoSomething(), or whatever()):
Compared to other languages, LabVIEW does have several limitations, but I can assure you that the core OOP mechanisms are the same as in mainstream OOP languages such as C# and Java. You still have inheritance, encapsulation, method overriding, interfaces and access scopes.
09-07-2026 07:24 AM
My class hierarchies tend to have different Create methods for the different child classes, as they often take different parameters. Of course you can make the Create function take a parameter object class that encapsulates such details but that can be often overkill. So my child classes usually implement their own specific "Create <class name>" methods that all have their unique name according to the class and don't overwrite any Create base class method. The base class may provide an Init method that all the Create methods usually call to do the common initialization for the base class private data and possibly can overwrite but then are required to call anyways..
09-07-2026 09:17 AM
I'd just set an error in the Base Create. And if it should be callable from children, check the incoming class ref so it isn't the base class. I don't understand why it should be inherited at all, usually i have unique Creates for a class.
09-07-2026 09:19 AM
I think that the name Create() is misleading.. I'm not sure that 1984 is using it as a real constructor...
09-07-2026 09:33 AM
@Yamaeda wrote:
I'd just set an error in the Base Create. And if it should be callable from children, check the incoming class ref so it isn't the base class. I don't understand why it should be inherited at all, usually i have unique Creates for a class.
If you have 15 child classes need to be set up in the same way and 1 which requires a unique setup then would create 16 different setups of which 15 are the same? But as always: I have no idea, I just try asking questions to solve my problems, and there is always a chance that my question does not make sense.
09-07-2026 11:33 AM
Basically the Create() usually has only a class output so needs to be specific to each class anyhow. If you have a lot of stuff that needs to be done for each of them that could be put into an Init() method in the base class.
Alternative is that you have to create a class constant of your specific child class and wire it to the class object input of your Create() dynamic dispatch method that you can overwrite in specific classes. But that is not really how a Create() object method should work. IMHO Create() really should be like a constructor for a class that creates the correct class object itself, not depend on a class constant that defines the desired class for a dynamic dispatch method. However I tend to have a high aversity to class constants on the user calling diagram. Your mileage may vary.
09-08-2026 01:51 AM
@1984: are you familiar with other programming languages?
If so, what we are trying to convey is that Create() has the same purpose as the built-in constructor new (C# and Java), or __init__ (Python).
There are all constructors. Its purpose is to create and initialize an object using a specific set of input parameters.
Person person = new Person("John", 35);
@1984: If you have 15 child classes need to be set up in the same way and 1 which requires a unique setup then would create 16 different setups of which 15 are the same?
The constructorS instantiate and 'configure' the child objects. The constructor should receive and store all the information required by the object.
You can then call a separate Init() method to perform the actual initialization operations using the data provided through the constructor. The base class implementation of Init() can contain the common initialization logic shared by the 15 child classes.
The 16th class, which requires a different initialization process, can override Init() and implement its specific logic.
This architecture works because Init() does not require class-specific input parameters. Everything it needs should already be encapsulated in the base or child class and populated before Init() is called.
For example:
Device is the base class and provides the common implementation of Init().TcpInstrument that requires an IP address and a port:
SerialInstrument that requires a COM port and a baud rate:Init() can be called without parameters.Init() uses the information already stored in the object to perform the initialization. If both child classes share the same initialization process, they can use the implementation provided by Device. If one of them requires different logic, it can override Init().