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

Deuippe!! Watching MICHAEL AIVALIOTIS' little video I see I have it backwards.  We load a **specific** child class using 'Get LV Class Default Value', then downcast it to its parent? That seems so backward to me.  Michael says "Class data traveling on a generic LabVIEW object wire" goes 'To more specific class'.  So we're doing the opposite of what I thought - we're starting with a child class, then downcasting it to its parent?

0 Kudos
Message 11 of 17
(1,272 Views)

Let me see if I can spell it out

 

The goal is to write application code where you only lay down parent functions and parent wires on your block diagram.  Consequently, when you create your child objects, you have to make them "look like" parent objects.

 

During initialization, you'll create a specific child object, and then *cast it* to the more generic parent class.   Now you'll have a child object that's able to travel along a parent wire.  When it arrives at a parent function, Dynamic Dispatch makes sure that what's *actually* executed is the child's own override function.

 

I found it kinda brain-bending too.  It didn't seem intuitive to me that the (parent) function seen on the block diagram is *NOT* the function that's actually executed.  But that's how LVOOP works.

 

The benefits of being able to *extend* functionality by deriving new child classes *depends* on generic-looking parent-level code on the block diagram. 

 

In a HAL, the parent will probably be an abstract class that doesn't implement any functional code in the functions it defines.  It exists as a base to inherit from and is the place where the interface to the member functions is defined.

 

Note: despite the simplified summary I've written so far, watch out for the urge to make an overly generic do-everything parent.  For example, consider the case where you need to manage a bunch of instruments that may be connected to a test stand.  There could be some kind of DMM, one or more Power Supplies of various types, etc.  You might be tempted to make a super-generic Instrument class that abstracts all the possible functionality of all the various instruments.  Resist this temptation!

    Instead, you should have a generic abstract DMM parent and a separate generic abstract Power Supply parent.  The part of your code that deals with DMM-like measurements would lay down generic DMM parent functions.   The part that deals with controlling power would lay down generic Power Supply parent functions.  

    At a certain point it's art more than science and you kinda have to start plunging in to get used to the thought process.  The most pure and elegant looking class hierarchy tree will often *NOT* be the most useful and practical one.  IMHO.   At the end of the day, the code is meant to serve a functional purpose, not win a beauty contest.

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
Message 12 of 17
(1,264 Views)

Kevin - fantastic explanation, I'm grateful for your help! We quasi-novices are SO lucky to have you experts to help us!  I think what I was missing were 1) the concept of  'child data traveling on a parent wire', and 2) the concept of downcasting a specific child class to a more specific parent class.  My intuition really struggles against that - I think of a child class as a specific type of its parent class (this is where I get going down the wrong path, I think).  The terminology really messes with my head.  The Help says

 

"Typecasts a reference, such as a control or a type definition, to a more specific class in the inheritance hierarchy.  For example, if Class A inherits from Class B, a variable of type B can hold a value of type A. You can use the function to downcast from type B to type A. If the typecast is invalid, this function returns an error at run time."

 

So we give the parent class (Class B) to the function as the "target class is the class to which you want to downcast reference. You can wire a class specifier constant or any wire of the target type to this input."  We give the child class to the reference input.

 

AHAH! Rereading the bit about "... a variable of type B can hold a value of type A".  Now I'm starting to get it.  Well, I just need to digest and practice.  Thanks again for your great help - paul

 

 

0 Kudos
Message 13 of 17
(1,261 Views)

Just to help you keep clear on terminology:

 

A child is *more specific* than a parent.  Always.

A parent is *more generic* than a child.  Always.

 

My impression is that people are more casual in their use of terms like "upcasting" and "downcasting" and don't all have exactly the same meaning in mind when using those terms.

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
Message 14 of 17
(1,254 Views)

Hey guys I've been fiddling with this a bit - created a bunch of classes.  No real methods yet, wanted to focus on class relationships.  BUT - sure seems like I went kinda crazy with the classes - this is like 3x more than I was thinking at first.  Can someone help me with a sanity check? Did I in fact get carried away?  Anduh - how come "Apply Icon to VIs" doesn't work? I have to go in and edit every child's icon - the demos I saw shows it happening automagically...  Here's my classes in 2025 - thanks!

0 Kudos
Message 15 of 17
(1,229 Views)

I'm no LVOOP expert, so don't take this as any kind of final word.

 

One key area of payoff is when you can take advantage of Dynamic Dispatch by having children implement specific behavior via override functions.  So I'd encourage you to consider ways to design your hierarchy so that you *can* get this payoff.

 

For me at least, defining the needed *functions* is part of figuring out what the class hierarchy relationships should be.  It's hard to say whether you've designed your hierarchy well or not until you also define what functions these classes have.

 

One brief specific comment.  The very few functions you've defined *might* be a good candidate for a generic "Write Params" function.  But to do so, you'd also need a more generic datatype for feeding in the variety of params needed by the different classes.

   In the HAL I worked on, such things were always fed in as an XML-encoded string.  This meant that the functions needed to parse through the XML to retrieve their actual typed parameters.  (This HAL was part of a combined TestStand / LabVIEW implementation.  If using LabVIEW alone, a Variant would be a more straightforward generic datatype to use for various classes "Params".)

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 16 of 17
(1,226 Views)

That makes sense Kevin.  Interesting about using XML encoding, never heard of that.  I guess it's 'self decoding', unlike, say,  "Variant To Data.vi".  Well, it is just plain ole LabVIEW, not Teststand.  In the 'receivers' of the parameters, I would know the data type to extract them.  Again, you've taught me something I had no idea of - thanks much! 

0 Kudos
Message 17 of 17
(1,207 Views)