LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Creating an array of objects of an unknown size and type at run-time

Highlighted

Hello

 

I am trying to create an array of objects. The objects in the array will be either based on a ChildA or ChildB class, both of which inherit from the Parent class. However, it will not be known until run time:

  • Which objects will to be inserted into the array; nor
  • The number of objects; nor
  • Their order in the array.

 

I have had some successful attempts building up to my requirements with:

  1. a single Parent object (01 – Set and Get name.vi),
  2. adding two Parents into an array of objects (02 – Set and Get name – Array of 2 objects.vi); and
  3. ChildA inheriting from Parent with one object (03 – Inheritance with one object.vi);

 

However, when I try to put two different child objects (ChildA and ChildB) into an array of Parent objects (’04 – Inheritance with 2 different child objects.vi) I come up with the following issues:

  1. There are coercion dots at both ‘InsertObjectParentName’ and the Replace Array Subset; and
  2. ‘getParentChildNameA.vi’ (as well as ‘getParentChildNameB.vi’) will not link to the output of ‘Index Array’.

 

Point 1 seems to suggest that it is not possible to link ChildA to Parent. However, ’03 – Inheritance in one object.vi’ shows a ChildA linking to the Parent input of ‘Parent.Set Name.vi’ without any coercion dots.

 

I would be grateful for any suggestions on where I’m going wrong. My attempts are attached.

 

Many thanks

 

RW

0 Kudos
Message 1 of 10
(1,069 Views)

The coercion dots are expected - you have an array of parent objects, and you are putting a child object into it - it needs to be coerced to the parent object type. When you pull that object out, it returns a parent object 'type', however the child class is whats actually there. LabVIEW has no way of knowing this at edit time - to perform operations on the child class after getting it from the array, you need to cast it to the child class type. Similarly, if you would like to get rid of the coercion dots, you need to cast the child class to the parent type before putting it in the array. I am not sure if there is a big execution speed difference either way. 

 

 

What is your goal here? Can you create dynamic dispatch methods for the parent that the children override when you retrieve the child classes from the array? 

 

0 Kudos
Message 2 of 10
(1,048 Views)

So the getParentChildNameA and getParentChildNameB can only be used by those respective and their children.  Parent cannot call those since they are not defined at the parent's level.  To get what I think you are after is to make the getName.vi dynamic dispatch and then override in the children classes.


There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
0 Kudos
Message 3 of 10
(1,037 Views)

Many thanks for the help so far.

 

My attempt is a simplified way of attempting to fulfil what I’m trying to achieve before applying it to the main programme.

 

I’m trying to have just one array of OO objects containing more than one type of object (eg ChildA and ChildB) that all inherit from the same class (eg Parent). This array will be of type ‘Parent’ as this is the common class for all the children.

 

LabVIEW array of objects.jpg

Figure 1 From LabVIEW's page - http://zone.ni.com/reference/en-XX/help/371361P-01/lvconcepts/creating_classes/ )NOTE: the use of Build Array has also been used with ChildA and ChildB which results in an Array of Parent.)

 

The difficulty arises when I want to access a child function (eg setChildNameA) when I use the ‘Index Array’ function. Even though a ChildA object has been stored a Parent object is returned; this Parent cannot access ‘setChildNameA’. This seems quite obvious, but I thought LabVIEW coped with this method of inheritance behind the scenes thus allowing the Child functions to be accessed.

 

I have placed a probe at a couple of locations as follows:

Location of probe

Probe Display

Comments

Output of

‘SET CHILD A NAME’

 set child name.jpg

The contents of both ‘NameParent’ and ‘NameChildA’ are as expected in this situation.

Output of

‘Index Array’

 index array.jpg

The data for ‘NameParent’ is as expected (ie an empty string).

 

However, this only returns the data available for the Parent, whereas data for the Child is also needed.

 

 

 

 

The above suggests that once the Child object is inserted into the array only the Parent’s data is seen even though the ‘Actual Data Type’ is a Child.

 

Thanks for the idea of using the dynamic dispatch approach. However:

  1. As I’m wanting two different objects in the array wouldn’t the Parent still be the common class using this approach?Wouldn't this mean that I have the same problem of the Parent being returned from the Index Array even though ChildA or ChildB has been inserted into the array?

Am I right in thinking that what I want to achieve is not possible in LabVIEW?

 

Thanks

 

RW

0 Kudos
Message 4 of 10
(995 Views)

@rw2018 wrote:My attempt is a simplified way of attempting to fulfil what I’m trying to achieve before applying it to the main programme.

 

I’m trying to have just one array of OO objects containing more than one type of object (eg ChildA and ChildB) that all inherit from the same class (eg Parent). This array will be of type ‘Parent’ as this is the common class for all the children.

 

The difficulty arises when I want to access a child function (eg setChildNameA) when I use the ‘Index Array’ function. Even though a ChildA object has been stored a Parent object is returned; this Parent cannot access ‘setChildNameA’. This seems quite obvious, but I thought LabVIEW coped with this method of inheritance behind the scenes thus allowing the Child functions to be accessed.

The above suggests that once the Child object is inserted into the array only the Parent’s data is seen even though the ‘Actual Data Type’ is a Child.

 

Thanks for the idea of using the dynamic dispatch approach. However:

  1. As I’m wanting two different objects in the array wouldn’t the Parent still be the common class using this approach?Wouldn't this mean that I have the same problem of the Parent being returned from the Index Array even though ChildA or ChildB has been inserted into the array?

Am I right in thinking that what I want to achieve is not possible in LabVIEW?

 

Thanks

 

RW


Hi,

 

if I understand correctly what you are trying to achieve, you have a lkittle misunderstanding of dynamic dispatching - but what you want is actually possible!

When different child objects are returned from your array they will call their own method e.g. "setname.vi" even if you can see only the parent method on your block diagram. But to make this dynamic dispatch possible you need 3 different VIs with the same name(!). Just add a "setname" method to your parent class.

 

I hope that helps.

 

 

 

ʍolɟɐʇɐp ʞuıɥʇ
0 Kudos
Message 5 of 10
(982 Views)

@rw2018 wrote:

The above suggests that once the Child object is inserted into the array only the Parent’s data is seen even though the ‘Actual Data Type’ is a Child.

 

Thanks for the idea of using the dynamic dispatch approach. However:

  1. As I’m wanting two different objects in the array wouldn’t the Parent still be the common class using this approach?Wouldn't this mean that I have the same problem of the Parent being returned from the Index Array even though ChildA or ChildB has been inserted into the array?

No and no.  Even though the wire type is of Parent, Child's data is still there.  You can just only use methods that have been defined by Parent.  When you have a Dynamic Dispatch method, the parent is defining the interface of that method.  What happens inside of that method is based on what object it was initialized as.  If a child overrides the method, then the child's method will run.  This is the heart of Inheritance and Polymorphism.


There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
0 Kudos
Message 6 of 10
(981 Views)

 

 Thanks for the feedback.

 

@crabman wrote:
Just add a "setname" method to your parent class.

@wrote:
You can just only use methods that have been defined by Parent.  .

As I understand it then, if I want to create a new function in a Child then I also need to define it with the same name in the Parent but as a dynamic dispatch and then use the Parent's version of the function in the VIs?

0 Kudos
Message 7 of 10
(969 Views)

@rw2018 wrote:

 

 Thanks for the feedback.

 

@crabman wrote:
Just add a "setname" method to your parent class.

@wrote:
You can just only use methods that have been defined by Parent.  .

As I understand it then, if I want to create a new function in a Child then I also need to define it with the same name in the Parent but as a dynamic dispatch and then use the Parent's version of the function in the VIs?


 

Yes, that will get you what you want, but may not be the best design choice.

 

Is child B also going to have its own override of this method? What about child x? Or are you just putting it in the parent class because child A needs it? If thats the case, I would rethink your design. 

0 Kudos
Message 8 of 10
(966 Views)

@paul.r wrote: @paul.ross

 

Is child B also going to have its own override of this method? What about child x? Or are you just putting it in the parent class because child A needs it? If thats the case, I would rethink your design.  


Yes, eventually, ChildA will have functions that ChildB won't have and visa versa. In that instance, these would only put into Parent because the child needed it. What sort of redesign would you suggest?

0 Kudos
Message 9 of 10
(959 Views)

@rw2018 wrote:

@paul.r wrote: @paul.ross

 

Is child B also going to have its own override of this method? What about child x? Or are you just putting it in the parent class because child A needs it? If thats the case, I would rethink your design.  


Yes, eventually, ChildA will have functions that ChildB won't have and visa versa. In that instance, these would only put into Parent because the child needed it. What sort of redesign would you suggest?


Well, you are designing your parent based on the details of children - this is a violation of the dependency inversion/Liskov substitution principles. If you do this for every case where a unique child needs something in the parent, your parent class will end up with a big mess of methods that arent relevant to all children.

 

What is your end goal? If I store a bunch of classes in an array, its usually because I have a set of operations I want to perform that are common to all child classes that would be in the array. I don't know what your application looks like and what you are doing with the array, but if you have specific operations that are only applicable to a child class, cast the object to the child class. However, as soon as you do that, you are kind of assuming that you will always place child class x in index y of the array.. which isnt a great design either.. 

0 Kudos
Message 10 of 10
(955 Views)