04-27-2015 07:34 PM
Here's one of those tasks that seems like it should be easy but might not be possible.
I'd like to make a cluster of objects (of sibling classes) whose private data is known at edit time. So far this has required two clusters, one of object constants and one of data constants to hand to those objects at runtime. Is there a one cluster solution?
We've had trouble keeping the two clusters of objects and data synchronized. It leaves room for mistakes.
Of course this is easy with other types. Add numeric constants to a cluster constant and that one place modification is distributed throughout the application complete with the edittime value. That's what we need... just with objects.
I realize this is part of the "LabVIEW doesn't have constructors!" design choice, but it still seems weird that it takes runtime work to set edittime data values. So I wonder if I'm missing an obvious way of doing this.
Has anyone found any tricks with this sort of thing?
04-27-2015 07:43 PM
I thought you could set default values in your private class control for each class?
To be fair, I don't think this is best practice; personally I actually prefer strategy you presented (admittedly load said values form a retentive source like a file) in order to keep the logic of the classes segregated from the class "constants".
04-27-2015 07:55 PM - edited 04-27-2015 08:01 PM
To use the standard object oriented auto analogy, we have a known collection of cars and trucks, and we want their license plate numbers in the private data. All of this is known at edit time and is constant.
Right now we have one cluster of plate numbers and one cluster of cars and trucks. Adding a new vehicle means adding to both clusters, taking care to preseve order, which has been problematic when there are dozens involved.
Yes, one solution is to make a brand new class with its own plate number as default value for every single auto, but that's even more hassle (and seems like overkill). And like you said, tky007, gets kind of weird into mixing data and logic.
04-27-2015 08:20 PM
Who says you can't make your own constructors? Just make a VI that accepts the license plate number and out comes the parent class. You could then downcast from there as necessary or you could just have it accept an object as well.
04-27-2015 09:06 PM
crossrulz, sure such a constructor can be used, but that's not the part of this problem that's missing.
Even with the constructor, how do I get the created objects into a cluster with names (so can't make an array and then array to cluster it)?
I would have had to previously define the cluster with placeholder object constants and the necessary names, which is fine. Except that at the same time I'm having to specify the plate numbers elsewhere. And that's how we get to two lists that can get out of sync.
So yeah, I'd accept that labview just can't do what I'm looking for, but I wanted to make sure I wasn't overlooking something.
I think my solution is going to be a cluster containing clusters of object, licenseplate. At startup I'll fold the license plates into the objects and just be stuck carrying around all of the now-superfluous license plate records the rest of the time. Annoying but acceptable.
04-27-2015 09:50 PM
@crcarlin wrote:
crossrulz, sure such a constructor can be used, but that's not the part of this problem that's missing.
Even with the constructor, how do I get the created objects into a cluster with names (so can't make an array and then array to cluster it)?
I would have had to previously define the cluster with placeholder object constants and the necessary names, which is fine. Except that at the same time I'm having to specify the plate numbers elsewhere. And that's how we get to two lists that can get out of sync.
So yeah, I'd accept that labview just can't do what I'm looking for, but I wanted to make sure I wasn't overlooking something.
I think my solution is going to be a cluster containing clusters of object, licenseplate. At startup I'll fold the license plates into the objects and just be stuck carrying around all of the now-superfluous license plate records the rest of the time. Annoying but acceptable.
To be fair, I'm not sure what you are asking for is achievable in a lot of other OOP languages either. Objects, by definition, are based on a template. While a class can have the same value for all objects (ie. static data) any data that differs between instances requires you to create said instance and set that data.
If you are looking for an easy way to "dictionary" objects so that you can obtain the right object when needed then you could just use a variant to store the objects by name into atributes.
04-27-2015 10:47 PM
Frankly, I have no idea what you are talking about. If you have a cluster of objects, the private data for those objects are stored in the object. My advise is whatever you think you know about OOP from other languages -- forget it. It is of little or no use in LabVIEW. In LabVIEW a class is basically a fancy cluster. An objects is an instance of a class, so in LabVIEW because there are no named variables, an object is a wire.
The typical way I instantiate classes is with the technique that Tim referenced, and is an excellent recommendation. If you want to call such a VI a "constructor" fine, just be clear that all you are really doing is initializing the data on a wire. Which by the way, is the same with any data on any wire. If you want an item in a cluster to have a specific value, you have to initialize it.
You might want to read up a bit, here and here.
Mike...
04-28-2015 11:29 PM
Constructors aren't really what I'm asking about here. I only mentioned the word because the "Decisions Behind the Design" document talked about initial values in that section. This also has nothing to do with design patterns in any other language.
So since there is confusion, let me try to phrase it from a different direction: fancy clusters.
I'm on board with the point that classes are basically fancy clusters, maybe even fancy cluster typedefs, right? And if I need to make a cluster containing some of these typedefed clusters I can just pop them right down on the BD with the edit time values set.
But classes are different. If I put objects into that containing cluster I can't set edit time values there; I have to set them elsewhere and apply their values at runtime.
If I want to add five cars and two trucks to the containing cluster I have to also--elsewhere--place five car license plate constants and two truck license plate constants, applying the plate numbers to the car objects at runtime (even though I know their values at edit time).
So that making of two separate lists is what we need to avoid. We need to avoid having types in one place and values in another.
I don't believe there're any way to produce a cluster of vehicles with license plate numbers set without involving two lists. I'm trying to see if anyone knows a way to do it that I'm missing.
04-29-2015 01:03 PM
Hey crcarlin,
I may be misunderstanding what you're trying to do, but would you be able to just create an array of clusters (and inside these clusters have your runtime data), and then index the array and unbundle the individual clusters to initialize your classes? This would be the "one-list" idea that you're talking about and would keep your data synchronized.
Forgive me if I'm misunderstanding your application, but please let me know what you think of this!
04-29-2015 02:30 PM
@crcarlin wrote:
But classes are different. If I put objects into that containing cluster I can't set edit time values there; I have to set them elsewhere and apply their values at runtime.
If I want to add five cars and two trucks to the containing cluster I have to also--elsewhere--place five car license plate constants and two truck license plate constants, applying the plate numbers to the car objects at runtime (even though I know their values at edit time).
So that making of two separate lists is what we need to avoid. We need to avoid having types in one place and values in another.
I don't believe there're any way to produce a cluster of vehicles with license plate numbers set without involving two lists. I'm trying to see if anyone knows a way to do it that I'm missing.
(bold emphasis mine for clarity) Yes; and this is true of virtually every OOP language I am aware of. Many OOP languages allow you to serialize the contents of an object and then re-load in at run-time (which is what I suggested earlier) or retrieve a static copy of a known initialised type of the class but you still need to setup the object at run-time programtically.
LabVIEW conveniently allows you a "const" data type for fundamental data types, including ones in a cluster. This isn't true for classes since their private data is just that - private and only accessible by the class itself, not the callers of your class methods.
I'm not sure I fully understand why you can't set the attributes you need when creating the cluster of cars and trucks originally; you did say that the license plates are basically constants in your application and known at compile-time.
Perhaps classes are not the best option for your scenario.