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.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Error using "To More Specific Class" inside parent dynamic dispatch VI

Solved!
Go to solution

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

 

Capture.PNG

 

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.

0 Kudos
Message 1 of 17
(4,576 Views)

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?


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 2 of 17
(4,570 Views)

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

CAUTION! New LabVIEW adopters -- it's too late for me, but you *can* save yourself. The new subscription policy for LabVIEW puts NI's hand in your wallet for the rest of your working life. Are you sure you're *that* dedicated to LabVIEW? (Summary of my reasons in this post, part of a voluminous thread of mostly complaints starting here).
Message 3 of 17
(4,561 Views)
Solution
Accepted by topic author Steve_the_Red

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

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 4 of 17
(4,550 Views)

Excellent point, thank you Ben and Kevin.  And thank you to crossrulz.

0 Kudos
Message 5 of 17
(4,521 Views)

@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. Smiley Wink

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 6 of 17
(4,481 Views)

@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.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 7 of 17
(4,475 Views)

@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.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
Message 8 of 17
(4,474 Views)

@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.

 

FInd_Plugins.JPG

 

Giving credit where it is due... I believe I learned that it was either Tomi Maila or Ton Plomp that taught me that. 

 

Spoiler
Regarding the missing error cluster wire between loops. I did tht myself and nobody had to teach me how to do that. Smiley Sad

 

 

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 9 of 17
(4,466 Views)

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

0 Kudos
Message 10 of 17
(3,361 Views)