Introduction
In this post I'm going to cover how LabVIEW represents a Class. At the most basic level, LabVIEW programs consists of data being processed by Virtual Instruments (VIs); that is, a LabView application consists of functions called Virtual Instruments that operate on the data passed to it, returning zero to many pieces of data. It's no different to any other programming language in that respect except that the syntax, if I can call it that, is wholly visual rather than text based. A Class then is just a mechanism used by LabVIEW to provide a wrapper around a set of data (attributes) and VIs (methods.)
Table of Contents
Anatomy of a Class
In this video I walk through, amongst other things, the structure of a LabVIEW class, its attributes and methods, a method interface and a discussion on by-value and by-reference. TLDW; the following sections give a much briefer overview.
Anatomy of a Class, Briefly
So the image above shows the make up of a Class: nothing different really to any other OO language. Attributes are ALWAYS private and can only be accessed directly by the class itself, so accessor methods must be created if non-private access is required. These can be created automatically by LabVIEW, including the Block Diagram implementing the functionality. Methods can be defined as Static, only accessible by an instance of the class in which they are defined, or Dynamic Despatch, accessible by the class or its subclass. In practice, this means you can pass any subclass into the method and it will work on that instance. Methods can be overridden in this manner; it is not possible to overload a method.
Opening the Setting.ctl item:
Here you can see that a class' private attributes are all contained within a Cluster, a Container type in LabVIEW that groups one or more controls together. In this case, two String controls to hold a Name and a Value. The previous image shows the Accessor methods created for these: Read XXXX and Write XXXX.
Opening Read Name.VI shows the Front Panel:
So the method's parameters are termed Controls and the outputs are termed Indicators. These are wired in a Block Diagram by connections to the appropriate terminal (one per input control and one per output control) on the Terminal Block. LabVIEW will load the appropriate control with the data passed along a wire connected to its terminal and will load the wire connected to the terminal of an indicator.
Looking at the Block Diagram for Read Name and Write Name:
These block diagrams show how the controls and indicators are wired up. More importantly, they show the by-value nature of LabVIEW: copies of the incoming instance's attributes are taken at many points. For the Read Name function, the input Setting instance has its attributes copied and passed to a NEW instance to pass as an output value. Setting In and Setting OUT are NOT the same instance in memory (i.e. these are not references.) Note how the Write Name function does not wire the Setting In directly to Setting Out. Instead, the copy of its attributes are updated with a new name value then this copy is used to populate a NEW instance of a Setting for passing as an output value.
What if I made a mistake and forgot that these copies occurred - i.e. I assumed I was given an object reference and was updating the single instance passed in and passed out:
If I assumed a by-reference architecture it would look like the above and I would think that when I changed the Name, I was changing it on the single instance referenced. However, because it isn't by-reference you can see that when I change the Name value, it is on a copy of the data and is then discarded because I don't carry it forward to the Setting Out.
Summary
- Class make up is similar to other OO languages.
- Access Scoping is used to control what other classes can access the methods of a class instance, just like other OO languages
- It's extremely important to remember that LabVIEW works by-value and not by-reference. It's easy to make a mistake when you are used to a more traditional OO language where objects are accessed by-reference.
Next: Setting up the Raspberry Pi Pico