10-22-2019 06:49 AM
I initialize the parent with some values and then create a setter method to copy the parentdata to the child. I hope there is an easier way, because my parent holds a lot of data
10-22-2019 07:21 AM
I see your mistake.
Just use the parent methods on the child wire.
You can call parent methods on Parents, children, grandchildren.....
You're overcomplicating things.
Shane
10-22-2019 07:40 AM
@s.h._tech wrote:
I initialize the parent with some values and then create a setter method to copy the parentdata to the child. I hope there is an easier way, because my parent holds a lot of data
Why? Just create an Initialize for the child and make it "Call Parent Method". You will need to have the connector panes match, but Dynamic Dispatch will do all of the work for you. Attached is an update to your project showing how this works.
But what you seem to be trying to do is not inheritance, but composition. Composition is when an object contains another object in its private data. So what exactly is the relationship you are trying to make here?
10-23-2019 12:43 AM
@Intaris wrote:
I need to do the first option, because there are more VIs called before the parent is ready to transfer the data to the child. The calling of the parent methods works. At least for methods created after the children. The older methods are not always recognized, but when I create a new dynamic dispatch and copy the whole VI it works for some reason. The classic inheritance works now.
I want to access all the data from the parent defined in parent.lvclass without creating a cluster in the definition of the class (which is already a cluster). But this has more cosmetic and accessibility reasons.
10-23-2019 01:41 AM - edited 10-23-2019 01:42 AM
@s.h._tech wrote:
@Intaris wrote:
I need to do the first option, because there are more VIs called before the parent is ready to transfer the data to the child. The calling of the parent methods works. At least for methods created after the children. The older methods are not always recognized, but when I create a new dynamic dispatch and copy the whole VI it works for some reason. The classic inheritance works now.
Red point: Hmm... Why does the parent transfer data to a separate child object? You should just have a Child object, and store the necessary "parent-level data" in the same child object, using the Parent VIs (e.g. iniparent.vi).
Blue point: I'm confused what this means... I suspect at some point you've changed how you're creating something, perhaps from the wrong way to the right way, and now it's "working", but I'm still unsure what you're doing, so I'm not sure it's right! 😞
@s.h._tech wrote:I want to access all the data from the parent defined in parent.lvclass without creating a cluster in the definition of the class (which is already a cluster). But this has more cosmetic and accessibility reasons.
The way you talk about Children and Parent classes makes me wonder if you in fact need a "Composition" arrangement as was previously mentioned by crossrulz, or if you're missing a key point about LabVIEW objects.
I know that when I first started using them, I also worked to place the entire parent object in the Child data using variants. When I later came back to that code, I was mystified as to what I'd been trying to do. My best guess is that I just hadn't understood dynamic dispatch very well! Some rework with the template pattern removed a large fraction of the code and made everything much cleaner.
Shane (Intaris) already mentioned (although not by name) the Liskov Substitution Principle, paraphrased as "every child is-a parent", or similar phrases. If you have a "is like a" relationship, don't use inheritance.
LabVIEW only allows public inheritance, and currently (wink wink 😄 ) doesn't have interfaces, so you can only correctly model "is-a".
For other relationships, look to composition (i.e. put an object of one class in the private data of another class).
What are your parent and child classes? Datahandler and Input? And how do they work (a description is probably fine).
Based on the names, I'm not sure that "Input" is-a Datahandler, or really that Datahandler is-a "Input", but perhaps that is indeed the case and I just haven't understood the meaning of the names correctly.
What are their respective initialization steps? Or rather, which VIs must you call on each object before you can use it? Do they share code, or purpose? Or does one just use the other (this is a composition/aggregate rather than inheritance relationship, usually).
10-23-2019 02:10 AM
Thanks for the detailed answer.
Since the Childclass now allows the Parentmethods I would also think that something went wrong in the creation step. With the methods I created thus far I have no problems.
The only problem I have now is that I want to access all the data from the Parent.lvclass and not put in in another cluster (my real data consists of multiple clusters and I do not want a cluster in cluster in cluster structure). Then I can create a setter method and transfer all the parent data to the child.
10-23-2019 02:18 AM
Have just been skimming the conversation, but "transfer all the parent data to the child", that should never be needed. Either there is a misconception or the design is incorrect. You simply access data from the parent class from the child class. When you are running the code, the created sub-class object has/can access parent class data, without transferring anything to the child (depending on access, which needs to be protected-scoped for parent->child access).
10-23-2019 02:22 AM
From the code you just attached and the block diagram you show in your reply, you could now use the idea I suggested some time ago with a separate typedef'd cluster, not used in the private data, but only as an output. This would in your example be {Numerisch, Boolesch}.
If you don't want to bundle data specifically for output (not inside the private data, but in the accessor methods like "getparentdata.vi"), and you don't want separate accessors ("Get Numerisch.vi", "Get Boolesch.vi") then you must instead consider alternative ways to get/use the data.
You talk about a Setter method to set the data in the child, but it's still not clear why you're trying to do this. It's possible you feel like this is obvious, but it continues to escape me... Can you try explaining it some more?
Further, following my descriptions above, are you happy that your Child is-a Parent?
10-23-2019 02:49 AM
The 'datahandler' is the super class. I do some calculation, file manipulation, setting values that all 'Children' need. After the 'datahandler' has finished its initialization I create the 'Children' are created. These children now need the values of the 'Datahandler' (which where created earlier).
@cbutcher wrote:
From the code you just attached and the block diagram you show in your reply, you could now use the idea I suggested some time ago with a separate typedef'd cluster, not used in the private data, but only as an output. This would in your example be {Numerisch, Boolesch}.
I will use this method. I am used to have direct access to all variables of the super class without the need to implement specific setter methods from the parent (they share the same set of variables declared in the super class). It would be nice to unbundle the Elements of the 'Parent' directly in the 'Child'.
@cbutcher wrote:Further, following my descriptions above, are you happy that your Child is-a Parent?
A parent for which class? In this example? A child can have a child (with all the methods and variables of the parent -> grandchild), but I dont think I did it here
10-23-2019 03:08 AM
@s.h._tech wrote:
It would be nice to unbundle the Elements of the 'Parent' directly in the 'Child'.
And this is precisely what you can't do.
You create accessors for the parent, and use these inthe child isntead of direct cluster access.
This is how it works.
If you want to re-create all of the data in a child, then it's going to be really inefficient.