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: 

How does a parent class fit in between child and grandparent classes?

Solved!
Go to solution

Sorry guys, I'm really struggling with this.  I understood the Factory Pattern thus: We start by using "Get LV Class Default Value", which (from the Help) "Returns the class data for the class whose path you wire to the class path input".  That resulting class data is popped into the "Reference" terminal of "To More Specific Class".  The (usually totally empty) generic parent class wire is connected to the "Target Class" input.  It then "Typecasts a reference, such as a control or a type definition, to a more specific class in the inheritance hierarchy".  I just did NI's OOP for LV online course (THANK YOU NI for doing this during the pandemic!), and also in Michael Aivaliotis' video at https://vishots.com/005-visv-labview-class-factory-pattern/, they go get the child class data from disk (SomeChild.lvclass file) this way, and although I find it totally counterintuitive, they tell me it works.  The clearest explanation I've heard goes like this "We will use the parent class wire throughout the application, and it will transport the child class data as needed."  So, we'll be needing the child (or grandchild) class to access its data and use its methods.  So, for a grandchild, does the parent class wire (now output from the "To More Specific Class" function) contain this 2-level hierarchy of class data, I assume? 

 

So I have a sort of a hardware hierarchy that leads naturally to parent-child classes, and I'm wanting to set up a Hardware Abstraction Layer "plugin" architecture, cause the boss says 'make the software future-proof'.  Does any of this make a shred of sense? Much thanks for your patience, my elderly neurons are really feeling the burn...

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

Wait a minute - I'm not hallucinating about 'To More Specific Class' - i use it all the time to downcast control references - there, it works exactly as I'd think.  So im back to square zero with the Factory Pattern mystery.  Maybe the 'Target Class' becomes the parent class, and the function is used to "load" the child class data onto that target.

0 Kudos
Message 2 of 10
(2,776 Views)
Solution
Accepted by topic author PaulOfElora

Get Default Class for File returns the actual class (and its parent, and the parent of that and any more up to the generic LabVIEW Object. As it has to work for any possible LabVIEW class it only can return the generic object type. The wire still contains the entire class hierarchy, it just looks like a generic object. To more Specific Class changes the wire type for the diagram and at runtime will check that the actual class in the wire has indeed that type in its hierarchy (and fails if that class doesn’t exist in the hierarchy chain inside the actual wire).

 

The class hierarchy in the wire doesn’t change just the class the wire itself has (and that class determines what methods and properties you can access on it). On the generic LabVIEW object class you can access none so that wire is useless other than to transport other classes.

 

When LabVIEW encounters at runtime a method or property access for a VI with dynamic dispatch enabled it inspects the class hierarchy from the current class of the wire downwards and calls the last VI in the chain that is overwriting its parent method. That’s the whole magic!

 

You need to understand the difference between compile time class definition (the class the wire has and which determines what VI methods you can connect to that wire) and the class contained in the wire at runtime, which could be any child class of that wire.


- The compile time definition determines what you can wire together at edit time.

 

- The runtime class determines what will be executed for dynamic dispatch methods.

Rolf Kalbermatter
My Blog
Message 3 of 10
(2,731 Views)

It should be uncommon that you need to cast the class reference. In you factory you code with the base class and in the child classes you implement the methods as needed. Casting is only needed when there's some functions that differs between children and you need to access the specific one.

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
Message 4 of 10
(2,723 Views)

You nailed it - that's exactly the explanation I needed! I'd been thinking that 'Get LV Class Default Value' only obtained the (very specific) child class.  But 'class default value' contains the entire class hierarchy.  Perfect - thanks Rolf, paul

0 Kudos
Message 5 of 10
(2,704 Views)

That makes sense, Yamaeda - thanks for your help, paul

0 Kudos
Message 6 of 10
(2,702 Views)

Holy cow the neurons are really lighting up now, boys.  For a Hardware Abstraction Layer / plugin architecture, there will be a hierarchy of *methods*, getting more specific as I go down thru inheritance levels.  "Coarse" progressing to "Fine" specialization.  So just as the class *data* is hierarchical, so too are the *methods*.  WhuhHoa!

Message 7 of 10
(2,683 Views)

@PaulOfElora wrote:

Holy cow the neurons are really lighting up now, boys.  For a Hardware Abstraction Layer / plugin architecture, there will be a hierarchy of *methods*, getting more specific as I go down thru inheritance levels.  "Coarse" progressing to "Fine" specialization.  So just as the class *data* is hierarchical, so too are the *methods*.  WhuhHoa!


Heureka! \o/

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 8 of 10
(2,654 Views)

It sounds like you're getting it, but to add the classic "Vehicle" metaphor to the pile...

 

Think of LabVIEW as the "road". It takes instances of class "Vehicle" on the road. Child classes of Vehicle are Car and Motorcycle. Child classes of Car are Camry and F350.

 

From the point of view of the Road, anything on it is a Vehicle; it doesn't need any more info than that. That's your "generic parent object". Just because the Road views the things traveling on it as a Vehicle doesn't mean it's not *also* a Camry.

 

The wire type on screen is JUST the point of view of the object. Child and parent data is still always there, it's just how it's shown. Methods (like "pay toll") can be different. The Road just needs the abstract method "Pay Toll", which simply says "Any vehicle can pay a toll". You can then say OK, all Motorcycles get free tolls, so the concrete version of this is "Pay $0". Cars will vary, so you make a method "Camry.Pay Toll" and you pay $1. You then make F350.Pay Toll that pays $5, because it's hauling heavy stuff.

 

In LabVIEW, you can handle the objects as the highest common "thing". By default this is the LabVIEW Object, but that's usually not very useful for practical work- you usually only use those references for very generic object handling, like sorting an array or something. For a hardware interface, you'll probably have a base parent class of "Oven" or "Oscilloscope" that you'd be using, with child classes representing the specific hardware you're using.

0 Kudos
Message 9 of 10
(2,642 Views)

Thanks Bert - that's 1 of the biggest paradigm shifts IMHO to OOP (LabVIEW is the only language I've tried it in).  The idea of a "stacked", hierarchical data structure on one itsy bitsy skinny little wire.   But I guess other LV objects (controls, references, etc.) have this same sort of thing happening, and I'm comfortable using those.  Of course, the ginormous difference is - I can explore LV objects and fiddle with them until I get something to work - with OOP *I've* got to come up with the data/class structure! paul

0 Kudos
Message 10 of 10
(2,633 Views)