LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Using a class reference as an attribute of another class...

Hello.  I have another one of my possibly misguided ideas.  In my application, I need to open a communication channel between a slave device and a master device.  To avoid passing lots of data around, I figured I would make both the slave class and master class attributes of the channel class, since a channel is always between one slave and one master.  However, the slave can open a channel to more than one master (not sure if the converse is possible, but that's beside the point).  Since LV is pass-by-value, I figured this might cause problems.  Thus, when opening the second channel with the same slave, I think I want to add a reference to the slave object to the channel object, not a copy of the slave object.  That way, if an attribute of the slave object is changed by accessing the slave attribute of the first channel, the slave attribute of the second channel will also reflect this change.  So my question is: is this the way class references work in LV?  Am I about to implement an anti-pattern?  Someone please talk some sense into me...

 

Thanks,

-Jamie

0 Kudos
Message 1 of 11
(4,668 Views)

After doing some research, it appears that Data Value References would behave in the manner I'm looking for.  However, there are many caveats about DVRs to the effect of "if you want to use a DVR, you don't really understand data orientend programming" and the like.  Before I do something stupid, it would be great to get some insight from a knowledgable member 🙂

0 Kudos
Message 2 of 11
(4,656 Views)

What you're describing is certainly possible and a even a good idea in cases like yours (although I'm not sure I'm tracking your description 100%).  Could you provide a few references to the caveats discouraging the use of DVRs you mentioned?

 

There is a shipping example that might be of interest to you located here:

 

<LabVIEW Root Directory>\examples\Object-Oriented Programming\Reference Object

Tom L.
0 Kudos
Message 3 of 11
(4,647 Views)

I had to do something similar to this in one of my applications, and as you have mentioned I made use of DVRs to do so.  I ended up with something like this (I believe it fits what the "gang of four" book would refer to as a decorator pattern).  It could be used to pass any class "by reference".

 

  1. An abstract interface class (iTrigger in my example) defines the methods required.
  2. A concrete class (tTrigger in my example) inherits from the interface class.
  3. An extra "decorator" class (tTriggerRef in my example) inherits from the abstract interface and also contains a data value reference to an abstract interface.

 

So creating an instance of this class would look something like this:

 

tTriggerRef.png

 

The tTrigger class contains the hardware implementation.  The tTriggerRef "decorates" it and its constructor looks something like this:

 

tTriggerRef.lvclassInit.png

 

 

Each method on tTrigger Ref should simply read from the data value reference and make the appropriate iTrigger call:

 

tTriggerRef.lvclassStart.png

 

 

If you have created a class like this, you may split the wire and each copy will only contain a data value reference back to the original class created by the initialization routine. The class is threadsafe in that only one thread can access the underlying data at a time.

 

 

Best Regards,

John Passiak
0 Kudos
Message 4 of 11
(4,643 Views)

John,

 

Thanks for your reply.  If I'm understanding you correctly, your class diagram looks something like this:

 

Untitled.png

Is that correct?

0 Kudos
Message 5 of 11
(4,615 Views)

Or perhaps this is a better representation.Untitled2.png

0 Kudos
Message 6 of 11
(4,610 Views)

I guess I'm having trouble applying this to my situation... it appears that I don't need the decorator class.  Am I missing the point?

Untitled3.png

 

0 Kudos
Message 7 of 11
(4,607 Views)
DVRs are just fine. I use them in conjunction with OO all the time. Using them together can give you some really neat capabilities. On my website you can find the text of a paper i delivered on OOP at NIWeek last year -- the link in in my signatures.. Don't worry about what the dope told you, he was probably a C++ programmer...

Mike...

Certified Professional Instructor
Certified LabVIEW Architect
LabVIEW Champion

"... after all, He's not a tame lion..."

For help with grief and grieving.
0 Kudos
Message 8 of 11
(4,591 Views)

It's definitely not mandatory to use the decorator, you could just make the data inside the concrete class into DVRs and that class would behave how you want.  

 

The decorator is a bit more flexible as it allows you to create the class as "by value" or "by reference" depending on the situation (though you might never need to use "by value").  Also it might end up being less work--in my case I actually had several concrete trigger types and implementing this with a decorator allowed me to change all of them at once into references without having to modify the existing classes at all.

 

 

EDIT:  I actually looked at your class diagram--you could certainly have the reference simply contain an interface but not inherit from it.   You wouldn't be able to use referneces and concrete classes interchangeably though (but maybe it's desirable to have a distinction between the two types in your case).

 

 

Best Regards,

John Passiak
0 Kudos
Message 9 of 11
(4,551 Views)

Thanks John, I think I understand but I'll need to read your response a few more times to be sure.  I don't typically understand the nuances of when to use which architecture paradigm until I come across a use case for it serendipitously.  I'd like to get better at software architecture.  I suppose that will happen with time.

0 Kudos
Message 10 of 11
(4,540 Views)