LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How to call parent constructor VI inside child constructor VI (LabVIEW OOP question)

Solved!
Go to solution

Hi,

 

Suppose there are two LabVIEW classes:

  1. Class A.lvclass. This class inherits from LabVIEW Object.
  2. Class B.lvclass. This class inherits from Class A. In other words, Class B is a child of Class A.

Suppose that the Class A private data consists of a single string field named "String Field A", and that the Class B private data consists of a single string field named "String Field B".

 

Suppose that Class A contains a constructor VI named "Constructor A.vi". This constructor VI creates a new Class A object whose "String Field A" is set to "abc".

Suppose that Class B contains a constructor VI named "Constructor B.vi". This constructor VI creates a new Class B object whose "String Field B" is set to "def".

 

Main question

  • What is the best or recommended way to ensure that the "String Field A" field of Class B object output by "Constructor B.VI" contains the value "abc"? In other words, what is the best or recommended way to ensure that all fields that the Class B object inherits from Class A have been initialised as per the rules defined in the Class A constructor. In other words, how to best call "Constructor A.vi" inside (as part of) "Constructor B.vi"?

Secondary questions

  • Does the desired outcome require using any of the "To More Specific Class" and/or "Preserve Run-Time Class" primitives, or a combination of them, inside "Constructor B.vi"?
  • Can the desired outcome be implemented by calling the "Call Parent Class Method" primitive inside "Constructor B.vi"? Would this require that both "Constructor A.vi" and "Constructor B.vi" share the same VI name, for example "Constructor.vi"?
  • Should the inputs and/or outputs of the two constructor VIs be static or dynamic? I would like both constructors VIs to NOT use any inputs of Class A or Class B type. Ideally I would like "Constructor A.vi" to output a Class A object (static or dynamic output), and "Constructor B.vi" to output a Class B object (static or dynamic output).

I have tried a few variations of using the primitives mentioned above, and have read the following NI Community and LAVA posts, but have not quite managed to get it to work yet:

Side-note

In C#, by default a constructor of a child class automatically calls the constructor of the parent class. This default behaviour seems very useful (it can also be turned-off or avoided when not needed). I'm essentially trying to replicate that behaviour in LabVIEW.

 

Screenshot 1: Sample C# code

1.png

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Screenshot 2: The result of running the code above. This shows that the Class A constructor was called implicitly inside the Class B constructor.

2.png

 

 

 

 

 

 

 

 

 

Many thanks!

0 Kudos
Message 1 of 4
(373 Views)

All of your suggested options are workable, see attached example

constuctors.png

Message 2 of 4
(326 Views)
Solution
Accepted by topic author Petru_Tarabuta

Hi Petru,

 

With LabVIEW classes, there is no such thing as a "constructor" as seen with OOP in text-based languages like C#. But you can imitate the constructor concept at the cost of some compromises.

 

The most simple solution I can think of would be:

 

Make a dynamic dispatch VI named "Create.vi" in your base class, then go to Properties -> Item Settings, select "Create.vi" and check option "Require overrides of this dynamic dispatch VI to always invoke the Call Parent Class Method node". Then, each time you override the "Create" VI in a subclass, you will have to unconditionally call the parent "Create". Note that you are not forced to override it for each class. For example an "abstract" intermediary class may not require specific initialization.

 

A drawback of using a dynamic dispatch VI for the "Create.vi" is that you must input a class constant to it, which is not very practical. So you can create a static wrapper of all your Create VIs named for example "Create <ClassName>.vi", which takes nothing as input and simply calls the dynamic "Create" of the same class. You can even make the dynamic "Create" protected to hide it from the exterior of the class hierarchy.

 

Here is an example project that implements this solution.

 

PS: What I described is basically what is used by some class creation toolkits such as GOOP or G#, except they also implement the concept of "by reference" objects.

 

Regards,

Raphaël.

Message 3 of 4
(314 Views)

Thanks Artem.SPb and Raphaël. The examples you attached are crystal clear and answer my question perfectly, thanks!

 

Also thanks for your detailed notes, Raphaël. I will create static wrappers of all the public "Create <ClassName>.vi" constructors, and set the "Create" dynamic dispatch methods to protected, such that the latter are abstracted away from the users of the class hierarchy.

 

Constructors that take only primitive data types (string, DBL, Boolean) as inputs, or that take no inputs at all, and output the "fully" constructed object (constructed by sequentially calling all ancestor constructors from most distant ancestor to immediate parent) was my goal.

 

Kind regards,

Petru

0 Kudos
Message 4 of 4
(286 Views)