03-29-2020 05:38 PM
OK, I'm dipping my little toe into classes. I made a silly little project and wrote a little demo VI. Then I went back and added a few new values to the enum control that's part of my class control. I went back to my demo VI and tried to use/select one of those new values in the enum, but LO! It hadn't updated from the class. I was under the impression that the class control would "act like" a typedef'd cluster - that I could edit it in one place, and the change would update instances everywhere. My questions for you class old hands:
1) Am I completely misunderstanding the way a class control works? Shouldn't every instance auto-magically update from the class when I change it, or do I still need to make the controls typedefs?
2) Is the way I'm using this little bitty class remotely correct? I split the class wire to prove to myself that that would creat a new instance of the class, with its own unique data. Any insight much appreciated, paul
Solved! Go to Solution.
03-29-2020 05:57 PM
@PaulOfElora wrote:1) Am I completely misunderstanding the way a class control works? Shouldn't every instance auto-magically update from the class when I change it, or do I still need to make the controls typedefs?
2) Is the way I'm using this little bitty class remotely correct? I split the class wire to prove to myself that that would creat a new instance of the class, with its own unique data. Any insight much appreciated, paul
1. If you want an enum to update everywhere, it needs to be a Type Def. This will affect all of your controls and indicators on front panels and constants on block diagrams. I recommend putting the type def inside of the class as a publicly available type def. Then your Do Something vi can use the type def enum. Now when you add items, you just update the ctl file.
2. Yes, you can have many instances of the same class, each with their own unique data. I'm not sure what else you are trying to prove here.
03-29-2020 06:34 PM
thanks crossrulz. As I take NI's online course (free now!!) on OOP, and as I search for tips & answers, I see bargeloads of stuff about classes and typedefs. I see posts like "... I quit using typedefs the minute I started using classes/OOP". I got the idea somehow that typedefs got "absorbed" or "subsumed" into classes - but no, that's totally wrong, I see. Now - the way I was using typedef'd controls/indicators now changes totally. Now I have accessor VI's (yes, that use the same ole typedef'd things) to set/get the data in the class. So - typdefs are still typedefs.
03-29-2020 07:10 PM
I guess you understand the problem now, following crossrulz's post, but I want to draw attention to the coercion dot in the "Write Action.vi" in the folder you uploaded.
Since you changed the available values in ChoiceToString.lvclass:ChoiceToString.ctl (the private data), "Action" in the bundle by name in "Write Action.vi" was updated to match the new class value.
However, "Action" the control input was not. This means that callers are not changed (sort of good, sometimes) but that you get the result you saw.
If you replaced "Action" in the .ctl and Write Action.vi s with a typedef (but didn't change "Do Something.vi", you'd see coercion dots in Do Something.vi instead. Recreating the inputs (i.e. delete control, create control, or alternatively quick drop and Ctrl+P) would give you the typedef'd input control.
So yes, typedefs are still important when you want to update in multiple places.
All of your class objects will be updated by the change to the .ctl private data, but that doesn't mean callers and subVIs are also updated to match unless you use the typedef.
Hopefully this helps give a bit more detail.
03-29-2020 07:31 PM
Yes! I stubbed my toe on it and learned the lesson that it's not enough to update the class control and expect the change to ripple thru each vi that touches the class. This stuff is totally obvious to you guys that have used OOP in LV for years, but I'm really having to bear down to understand it! Thanks for the help, paul
03-30-2020 06:30 AM
@PaulOfElora wrote:
I see posts like "... I quit using typedefs the minute I started using classes/OOP".
That is only really valid for cluster typedefs. Admittedly, I very rarely have cluster typedefs anymore. One of the features of OOP is protecting the data in the private data cluster. You are blocking random VIs from changing things you do not want them to. For this reason, I will gravitate to a class over a cluster in most situations.
I still use enum typedefs all the time.
03-30-2020 03:16 PM
OK, I've run into a new question. I reckon everybody starts playing with classes with a) Timers, b) Vehicles, or c) Animals. I'm doing a timer. So I need to instantiate a timer object, initialize some of its data, then employ it inside 2 separate VI's. If I split the class wire and provide the 2 wires to the 2 VI's, I'll get 2 separate timers running with separate data, which I don't want - the 2 different calling VI's need to talk to the same, single, 'shared' timer with the same common data. Somebody can maybe tell me how my thinking is muddled does the question even make sense? Thanks, paul
03-30-2020 03:56 PM
@PaulOfElora wrote:
OK, I've run into a new question. I reckon everybody starts playing with classes with a) Timers, b) Vehicles, or c) Animals. I'm doing a timer. So I need to instantiate a timer object, initialize some of its data, then employ it inside 2 separate VI's. If I split the class wire and provide the 2 wires to the 2 VI's, I'll get 2 separate timers running with separate data, which I don't want - the 2 different calling VI's need to talk to the same, single, 'shared' timer with the same common data. Somebody can maybe tell me how my thinking is muddled does the question even make sense? Thanks, paul
What you are observing is the by-value and by-reference aspects of objects in LabVIEW. By default, LV objects are by value and branching a wire will effectively clone the class. When you need things to operate on a shared instance where branching the wire does not effectively clone the object than you need a by-reference class. The easiest way to achieve this is to put all of your class data into a DVR and your class private data than contains the DVR itself. Now when the wire is branched all instances of that class wire will have the same data. If there is static or constant data in your class private data that does not necessarily need to be in a DVR then. The DVR for your class data is a prime example of this.
03-30-2020 04:04 PM
thanks Mark, I'll have to digest this. I had a feeling that DVR's were looming darkly ahead for my next learning topic. What I see a lot of is DVR's being sold as a way to save memory and not make copies, but for this aspect, it's all about multiple processes being able to point to (as in pointer) a shared resource, I guess - paul
03-30-2020 09:24 PM
Wow, I've gotten totally confused. I tried bundling my 2 Event Refnums (which never change once created) along with a DVR made using my 'User Controls.ctl' data type. But then - ??? Can I get a hint of where to go next?