From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.
We appreciate your patience as we improve our online experience.
From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.
We appreciate your patience as we improve our online experience.
01-09-2018 11:11 AM
Hello,
I am receiving the following error: One or more of the inputs to this tunnel or shift register does not originate at the dynamic input front panel terminal
With this situation:
1) Parent class ("Parent") has several children classes ("Child1", "Child2", etc.)
2) At runtime, the user will select which child is in use.
3) Created a typedef in Parent containing the names of all the children
4) Created a dynamic dispatch VI in Parent that usese the typedef to control a case structure.
5) Based on the value of the typedef, Parent is cast to one of the children
I'm guessing the problem is that the VI is a method inside of the parent (i.e. if I didn't have this as part of the parent class, it would work fine), but it still seems like this should work. Perhaps there's a better way to do this (that actually works). If anybody has input or a solution for this, it is greatly appreciated.
Solved! Go to Solution.
01-09-2018 11:22 AM
I do not see the point of this VI. You are casting to a child class, but then that is just being coerced (casted) right back to the parent class on the output tunnel of the case structure. What are you really trying to do here?
01-09-2018 11:40 AM
LabVIEW classes require more careful thought and syntax when talking about the object wire. I like to say that Child objects "travel as" parents along a "parent-typed" wire when I view the block diagram source code.
At run time, dynamic dispatch often causes child override functions to execute *instead* of the parent function that appears on the block diagram.
So, the code no longer does quite exactly what its literal appearance would otherwise suggest. It's an important thing to keep in mind when dealing with LVOOP.
All that's background to say that I think you're approaching your app the wrong way. I'm not a LVOOP expert, but have done a bit with it here and there. When setting up an app to take advantage of dynamic dispatch, block diagrams tend to contain only the parent-level VI icons. The parent-level VI's do *not* try to keep track of who all their children are so they can cast to a specific child. They simply count on the child implementation to override the parent VI. The magic of dynamic dispatch is that the child object that travels on the parent wire will actually execute the child-level override of the given parent-level VI that's visible on the diagram.
Typically, when a user specifies a particular child object to be created, that child object will be cast to the more generic parent. Then this parent-looking wire that actually carries a full child object is used to feed all the parent-level dynamic dispatch VI's that children can override for specific behavior.
For you, I think you keep doing steps 1 & 2 from your post. Do NOT do 3,4, or 5. Instead, create a child, cast it to parent immediately after creating it, and move it around your application code on parent wires.
The specific cause of your error message isn't worth solving, the general cause of it is a kinda inside-out approach to using OOP that you need to change.
-Kevin P
01-09-2018 12:19 PM
if you are attempting to develop a Factory Pattern then all you need is a case structure that has each of the children in each case. No input wire required aside from the enum selector.
Ben
01-09-2018 03:46 PM
Excellent point, thank you Ben and Kevin. And thank you to crossrulz.
01-10-2018 09:24 AM
@Steve_the_Red wrote:
Excellent point, thank you Ben and Kevin. And thank you to crossrulz.
You are welcome.
Make me think I should be guessing more and answering less.
Ben
01-10-2018 10:11 AM
@Ben wrote:
if you are attempting to develop a Factory Pattern then all you need is a case structure that has each of the children in each case. No input wire required aside from the enum selector.
I actually prefer to use the Get LV Class Default Value. This is more flexible to add different children without having to change your code. In my case, I use a configuration file to state which child class I should use for a test setup. So from there, I just build the path of the class and load it. Need a different type of DMM? No problem! Just make the new DMM class, put it in a special folder, and it is ready to use with the already built executable.
01-10-2018 10:11 AM
@Ben wrote:
if you are attempting to develop a Factory Pattern then all you need is a case structure that has each of the children in each case. No input wire required aside from the enum selector.
Ben
In OOP a parent method should never have any knowledge of its children or descendants. It really breaks the whole concept of OOP. The factory pattern is a helper function which would know of the parent (or base class) and instantiate a specific instance of a child class based on some input or parameter. This should not be part of the base class since it violates the rules of OOP. A more flexible way of doing this is to use plugins so that the helper function does not need to be modified when new children class are added. It would load them from disk dynamically.
The case structure works fine if you will never, or very rarely adding children classes. If you foresee the need to add more children in the future you should really consider using a plugin architecture.
01-10-2018 10:40 AM - edited 01-10-2018 10:43 AM
@Mark_Yedinak wrote:
@Ben wrote:
if you are attempting to develop a Factory Pattern then all you need is a case structure that has each of the children in each case. No input wire required aside from the enum selector.
Ben
In OOP a parent method should never have any knowledge of its children or descendants. It really breaks the whole concept of OOP. The factory pattern is a helper function which would know of the parent (or base class) and instantiate a specific instance of a child class based on some input or parameter. This should not be part of the base class since it violates the rules of OOP. A more flexible way of doing this is to use plugins so that the helper function does not need to be modified when new children class are added. It would load them from disk dynamically.
The case structure works fine if you will never, or very rarely adding children classes. If you foresee the need to add more children in the future you should really consider using a plugin architecture.
That makes sense Mark.
This is an image from my gallery going back to about LV 8.2 where I did what I think you are describing.
Giving credit where it is due... I believe I learned that it was either Tomi Maila or Ton Plomp that taught me that.
Ben
04-02-2020 07:31 PM
This is exactly the thread I was looking for. I'm new to OOP, and I'm lurking around approaching a small, simple HAL. This pattern of
1) 'Get LV Class Default Value' (get a class from somewhere, maybe a file)
2) Wiring that into the Reference terminal of 'To more specific class' and wiring some class to the Target terminal
3) Using the output class to go Do Stuff unique (maybe) to the specified child class
Seems to me to be at the heart of this. So - are we first taking a parent class as the reference, downcasting it to one of its child classes, then implementing some specific method (Dynamic Dispatch method, right?) that is unique to the child? Do I have that right?
much thanks for the discussion, it's peeling the scales off - paul