LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Super basic Factory Pattern question

Solved!
Go to solution

Me again learning LVOOP the hardest way, trying to implement a HAL. It's a very basic & simple HAL, but I'm still a Fool Rushing In, as folks have pointed out😋.  I built some classes, wrote a bunch of methods, played around with them, all happy joy.  But now I'm starting to write the application, and my first step is to do the selections of the child objects to use for specific configurations.  But Lo!  I start down the "Get LV Class Default Data.vi" and the "To More Specific Class.vi" road that I've seen 100 times for the Factory Pattern implementations.  But a little question pops into my already small, overcrowded brain.

 

"Exactly, precisely, why do I need to even specify the parent classes for all my child VI's?"

 

Ok, I guess all I'm really looking for here is for someone to confirm for me the answer, which I think is this:

 

"Because, silly, you're going to need all those wonderful pieces of data/attributes. and all those wonderful-but-mostly-empty method DynoDispatching 'templates' that you set up for the parents!"

 

Yes or No? Thanks again and again, guys - paul

0 Kudos
Message 1 of 40
(3,451 Views)
  1. Open the class
  2. Right-click the .lvclass file
  3. Select Properties
  4. Click in the Inheritance category
  5. Click on Change Inheritance
"If you weren't supposed to push it, it wouldn't be a button."
0 Kudos
Message 2 of 40
(3,425 Views)

You are correct in thinking the purpose is to define what methods are available to the object.

 

In the simplest case, let's assume that you have two power supply classes (Keysight_PS and NI_PS) that both inherit from Abstract_PS which defines all of the methods you would want to run (Initialize, Generate_Output, Stop).

 

When you point to your NI_PS and "Get LV Class Default Value", you may know that this class inherits from Abstract_PS but during edit time LabVIEW doesn't know what this class is, only that it is a LabVIEW Object (theoretically you can pass a path to load any class). A LabVIEW Object doesn't know how to Generate_Output so you have to cast it to an Abstract_PS to gain access to that method.

 

Edit: The response is aimed at explaining why you would need to cast the generic LabVIEW object but is that what you are not sure of or are you not sure of why your child classes need to inherit from the parent in the first place?

Matt J | National Instruments | CLA
Message 3 of 40
(3,421 Views)

Thanks guys.  I haven't gotten too far before starting to take on water again.  I've created a 2-level inheritance structure.  I have some methods belonging to the middle layer ("IO Controller Class"), and I made one child of it, named "RIO-47200" (a specific IO controller).  Now, when I invoke a method belonging to the middle layer, it compiles.  But I thought I should be able to ?insert?/?load?/?cast? the middle class into the grandparent "!Controller Class", and run the same method on that (I'm still hazy on the terminology of using To More Specific Class).  But no joy, got a class conflict.

 

I made a snippet and a screenshot of the RIO-47200 hierarchy.  "RIO-47200" is a child of "IO Controller" is a child of the ancestor "!Controller Class".

 

I understood that I could define methods for, say, a middle layer class that aren't shared by other classes at that level.  My "!Controller Class" has only general stuff, communication data, etc.  I understood that I could (should) get more and more specific I descended down the tree.  But then trying try to use ancestor class is throwing me.  Any insight into where my thinking is wrong? Thanks, paul

0 Kudos
Message 4 of 40
(3,372 Views)

I should have emphasized - I do definitely plan on actually using the data owned at the ancestor level... via accessor methods.  But I clearly (or not?) understood that we build up these class objects with the intent to carry around the entire hierarchy in the object throughout the application. Wrong?

0 Kudos
Message 5 of 40
(3,384 Views)

@PaulOfElora wrote:

I should have emphasized - I do definitely plan on actually using the data owned at the ancestor level... via accessor methods.  But I clearly (or not?) understood that we build up these class objects with the intent to carry around the entire hierarchy in the object throughout the application. Wrong?


All children 'carry around' the private data of it's ancestors. The entire hierarchy isn't carried around.

 

That private data should only be there if it's useful, so it's not 'overhead'. It's required (or should be).

 

Because each child inherits from it's ancestors, and has all the private data of it's ancestors, each child is capable of using the methods of it's ancestors. That's really where the parent\child metaphor fails. Nobody inherit (and extend or change) their parents capabilities (positive and\or negative) just like that.

 

The 'hierarchy' of a class, at run time, is just a vtable-like structure. Probably just a few pointers. It's not heavy at all, or it wouldn't be performant at all.

 

My motivation for keeping the folder structure the same as my class hierarchy, is so I can easily copy paste class hierarchies to other projects.

Message 6 of 40
(3,343 Views)

@PaulOfElora wrote:

Thanks guys.  I haven't gotten too far before starting to take on water again.  I've created a 2-level inheritance structure.  I have some methods belonging to the middle layer ("IO Controller Class"), and I made one child of it, named "RIO-47200" (a specific IO controller).  Now, when I invoke a method belonging to the middle layer, it compiles.  But I thought I should be able to ?insert?/?load?/?cast? the middle class into the grandparent "!Controller Class", and run the same method on that (I'm still hazy on the terminology of using To More Specific Class).  But no joy, got a class conflict.

 

I made a snippet and a screenshot of the RIO-47200 hierarchy.  "RIO-47200" is a child of "IO Controller" is a child of the ancestor "!Controller Class".

 

I understood that I could define methods for, say, a middle layer class that aren't shared by other classes at that level.  My "!Controller Class" has only general stuff, communication data, etc.  I understood that I could (should) get more and more specific I descended down the tree.  But then trying try to use ancestor class is throwing me.  Any insight into where my thinking is wrong? Thanks, paul


Well, yes, you can cast a class and use the parents function (if it's implemented). It's probably the wrong way to handle it, generally.

If RIO wants to use IO Controller class' function, it should simply have a Call parent in its implementation. If you don't have any difference at all, you should simply not implement it, as OOP will check if the function exists further up in the hierarchy.

It sounds like you're trying to overthink/over specify again. 🙂 

If you create a RIO object and place the root objects Read in the code, it'll use RIO's method, if it exists. Else it'll use IO Controllers method, else it'll use the root objects method.

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

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 7 of 40
(3,338 Views)

Oh wow, i really hadn't grasped that. Yeah, for some reason I'd been thinking all these 3 weeks of LVOOP Boot Camp that one always uses the entire hierarchy of the classes  (where do i get these weird ideas? I've been using FP control objects for years without needing to carry the top level VI refnum). Thanks as usual for the light you've shown on OOP, wiebe - paul

0 Kudos
Message 8 of 40
(3,332 Views)

Thanks, Yamaeda (again) for helping me un-overthink this! I kinda thought that i needed the aircraft carrier when only the propeller was needed... paul

Message 9 of 40
(3,331 Views)

It gets easier. In the rate you're exploring, things should come together soon.

0 Kudos
Message 10 of 40
(3,314 Views)