LabVIEW Idea Exchange

cancel
Showing results for 
Search instead for 
Did you mean: 
Intaris

Allow for ABSTRACT classes/functions in LVOOP

I would like to make a small workind change on another suggestion found HERE.

 

I would like to be able to declare LVOOP classes as ABSTRACT.

 

One example is a spectrometer class I have developed which provides much of the needed functionality but which is not designed to actually DO anything (Get name, Set Name, GET calibration coefficients, SET calibration Coefficients and so on).  At the moment I can instantiate an object of this class as with any "VALID" class which then just returns an error at run-time because the functionality is not complete.

 

By preventing users from (either willfully or accidentally) dropping what is essentially an abstract class onto the BD of a program we could prevent some awkward bugs.

 

Shane.

23 Comments
Albert.Geven
Trusted Enthusiast
Sure, I like the idea, how do I vote?
greetings from the Netherlands
Intaris
Proven Zealot

Just click on the Kudos icon.

 

Shane.

AristosQueue (NI)
NI Employee (retired)

We've had large conversations about this feature. There are two questions that need to be answered:

 

1) Given that connector panes for functions in LabVIEW are defined by dropping controls of the given type, how do you have a type that you cannot drop and still write functions that take that type?

 

2) The one idea for solving #1 is to have any VI with these types on it not be runnable except when called by another VI. The abstract type could not be used as constants and any controls must be on the connector pane as required inputs. What does making a VI not runnable directly do to the debug experience of LabVIEW where users are used to being able to run a VI over and over to debug it?

 

The feedback so far on these two questions has been mixed, so we have been focusing on other features that are also highly demanded but where we are more sure of the implementation. 

 

[EDIT] I forgot about the other issue...various functions in LabVIEW return the default value of a wire type when an error occurs. The For loop tunnels output defaults when they execute zero times. What value would be returned for abstract classes that can never actually travel on wires? Preventing abstract classes from being used by something as common as the For loop or removing the Unflatten From String abilities would seem to be restrictions so tight as to make the feature unusable. 

Message Edited by Aristos Queue on 06-08-2009 08:21 AM
Intaris
Proven Zealot

@AQ

 

All valid points.

 

The problem with the behaviour when being treated as a perent type had occurred to me.

 

I may be way off on several points but the following is how I see things.

 

LV, even when displaying an array of objects shown as being of the "base class" actually knows what the REAL class of the object is.  It can get confusing (for me and hopefully for others too) sometimes to keep reminding myself that a wire with the apparent object datatype "base class" isn't in fact a "base class" object but something being handled as a "base class" object (downcasting).  As such the actual "base class" dynamic dispatch VIs are not being called.  As soon as a dynamic dispatch VI of an ABSTRACT "base class" is called, the editor should produce an error.

 

As such we need to differentiate between a "base class" object dropped onto the BD of a VI and a "base class" used as a connector or wired up to a "cast" function.

The first has the ACTUAL data type of a base class which as an ABSTRACT class should produce a broken wire when wired up to a function of the class.

The second is a downcasted object which is currently being INTERPRETED as having the satatype of "base class".

 

Both types have an origin somewhere in the source code.  What I'm saying is that we shouldn't allow an object of "base class" to be connected up to a function of the class.  If we eliminate the origins of an object of true "base class" datatype, haven't we solved the problem?

 

An object of "base class" will (in my example) result in a run-time error whereas the proposed mechanism would result in an edit-time error.

 

I have far too little insight into the inner workings of the LVOOP dynamic dispatch code but it seems to be do-able if we can prevent TRUE "base class" objects being wired up to a dynamic dispatch VI..... 

 

Shane.

 

PS Side-note: I think the restriction should apply to dynamic dispatch VIs only as the non-dynamic dispatch VIs of the base class have their functionality implemented and could be used even with a "base class" object as input.

Intaris
Proven Zealot

Another thing:

 

Regarding a FOR LOOP returning a (zero-size) array of ABSTRACT classes should indeed create an error as soon as that wire is connected to a dynamic dispatch VI of the class.  This would not prevent using FOR loops with abstract classes, it would simply force the user to either make sure the loop doesn't execute zero times or check the output and correct things before wiring up the result to a dynamic dispatch VI.

 

It all comes back to the same point really.  Don't allow an actual "base class" object to be wired to one of its dynamic dispatch VIs if it's class is defined as being abstract.

 

Shane.

AristosQueue (NI)
NI Employee (retired)

Regarding a FOR LOOP returning a (zero-size) array of ABSTRACT classes should indeed create an error as soon as that wire is connected to a dynamic dispatch VI of the class.  This would not prevent using FOR loops with abstract classes, it would simply force the user to either make sure the loop doesn't execute zero times or check the output and correct things before wiring up the result to a dynamic dispatch VI.

 

Breaking the VI when you wire it up wouldn't work. Here's a piece of code that you wouldn't be able to write:

ProblemCaseForAbstractClasses.png

If we break the VI as soon as an abstract class wire is connected  to a dynamic dispatch VI, this code wouldn't work because the For Loop *might* execute zero times and we won't know whether it actually executes zero times until the VI is already running and we see what value is passed into that "how many" control. 

 

Similar problem exists with Unflatten From String if you tell it you're unflattening a Graphics object... don't know which child object, but we expect it to be one of them. But if you get an error during unflatten, what value comes out on the wire? 

 

Intaris
Proven Zealot

The example you give is only impossible if the Editor allows "Class Factory" to return an actual "base class" object without first being properly cast to a child object.

 

If the output of Class Factory has a code pathway where a "base class" is returned directly then the wire should break.  If it doesn't have this possibility, then it shouldn't.  This is the simplistic view.

 

Regarding"unflatten From String" there could be two options

1) Don't allow instantiating abstract classes this way (probably not very attractive)

2) Leave things as-is and settle with a run-time error when some njon-implemented functionality is encountered

 

Regarding the zero-iteration FOR loop, here's another thought.... How about forcing an extra operator between the loop output and the first dynamic dispatch VI.  Something like "is Abstract class?" with a "default class" input with a requirement that the "default" class be non-abstract.   Awkward? Probably.

 

Which situations could give rise to a non-obvious "base class" object?

While loop

For Loop

Unflatten from string

Queues, notifiers and Events?

.... any others?

 

I would be quite happy even if the majority of cases were covered re: abstract classes i.e. no obvious direct path from an abstract class type to a dynamic dispatch VI.  The other cases (loops and unflatten) could be left as run-time errors with a mention in the help file.

 

I think some people would be unhappy with the mix of edit-time and run-time errors, but isn't it at least a step in the right direction?

 

I'm probably annoying you at this stage so I'll stop (for a while)......

 

Shane.

AristosQueue (NI)
NI Employee (retired)

> I'm probably annoying you at this stage so I'll stop (for a while)......

 

Nope. The feedback is useful. It gets more useful the more users chime in (hint to everyone else who might be interested in this feature ever happening...). The idea is still on the 4-or-more-years list just because of other more pressing (and already defined) projects. But the more we can define all the aspects we'd like to see in the language the more we can make sure that as we add features we don't perclude one of the features we'll want further down the line. 

Daklu
Active Participant

Let me see if I can summarize this accurately...

 

There is no such thing as a class on a block diagram or front panel.  They exist in the project window and on your hard disk.  Dropping a class on a vi automatically instantiates an object.  Since abstract classes cannot be instantiated, there is no way to put one on a vi.  What Shane is ultimately asking for is a way to use classes on block diagrams?

 

I voted for it, not so much because the use case mentioned bothers me, but because figuring out how to deal with abstract classes is key to what I want:  An Interface construct🙂

 

At the same time, I don't see a way to implement abstract classes (or interfaces) without really changing the way LV appears to behave to the user.

Intaris
Proven Zealot

Daklu,

 

No I'm asking for exactly the opposite of using "classes on block diagrams".  I'm requesting that a class which is labelled "abstract" cannot be instantiated (i.e. CANNOT be used on a block diagram).

 

And when I say "class" I mean an object of the class of course.

 

This leads to many problems as AQ has pointed out.

 

Shane.

Message Edited by Intaris on 08-10-2009 08:08 AM