Jump to content

LVOOP override implementation


Recommended Posts

This is still a beginner question, i am trying to understand LVOOP.

the two majors problems i have are in visualizing my project:

first, class view should be in tree like in the project, so we would know what who is child of who. having the classe occuping the same hierarchy in the project explorer is confusing.

but the most problematic thing i have is with dynamic dispatch: the staightforward implementation of LVOOP i see for now is the override method. but two problems arrise immediatly:

1) the vi cannot be saved under same name in same folder. the vi name does not include its class. thats very surprising, and mess up my organisation on the HD quite a bit. that forces me to have folders in the project explorer, in positions where it is irrelevant and even more confusing.

2) when reviewing the code, one has to pass trough all classes figure out which are child of which, and then find the vis with same name in those classes. is there no easy way to visualise all overriding vis? a right-click on the dynamic parent vi would be perfect, showing all combinations (classes) would be perfect.

one thing tough: i begin to see the potential, but i feel the learning curve is going to be long...

Link to comment

Hi Gabi,

I agree that LabVIEW can improve the ways that it allows you to visualize the relationships between classes. Here are a some thoughts...

  • You can see the class hierarchy from the View>>LabVIEW Class Hierarchy dialog.

  • You can use naming conventions to help distinguish between parent and child classes. For example, Heater.Simulator and Heater.Watlow are children of Heater.

  • You should organize your classes on disk, putting them each in a separate folder. It is better to organize them into a flat structure on disk (put all class folders in a "classes" folder), since you may decide to change the inheritance hierarchy later, and it's difficult to move entire folders around to reflect the new class hierarchy.

  • In LabVIEW 8.5, when you double-click on a dynamic method subVI on the block diagram, it opens the Choose Implementation dialog, which shows you a tree view of all the implementations of the different classes. Take a look at this blog article by Christina Rogers -- there is a video of how to use this great new feature.

Cheers,

-Jim

Link to comment

Go, Jim, go! :yes:

Jim answered most points. There's only one other to which I want to reply.

QUOTE(Gabi1 @ Oct 3 2007, 09:24 AM)

first, class view should be in tree like in the project, so we would know what who is child of who. having the classe occuping the same hierarchy in the project explorer is confusing.

Any tree can show only a single hierarchy. It is logically impossible for a tree to show multiple indepenent hierarchies. Although LV R&D has been working very hard to invalidate the logic of the universe on several key points, at this time, we are unable to circumvent "A == A" and "1 != 0". :P

The project tree shows the ownership hierarchy (so if a library owns your class, the class will be listed under its owning library). It does not show the VI call hiearchy. It does not show the LV Class hierarchy. It does not show the disk hierarchy (though in LV8.5, we added a second tab to the project that shows the disk hierarchy). It does not show the palette hierarchy. Other tools -- such as the two hierarchy windows -- exist to view other relationships between elements.

If we want to show many different types of relationships in the same display, that requires a graph, not a tree, which might be more complexity than many people care to deal with. So the project window remains a tree. However, one excellent tool for displaying and interacting with the graph will soon be released. Keep an eye open for the UML tool from Endevo which should be available soon.

Link to comment

QUOTE(Aristos Queue @ Oct 3 2007, 09:11 AM)

Although LV R&D has been working very hard to invalidate the logic of the universe on several key points, at this time, we are unable to circumvent "A == A" and "1 != 0". :P

Obviously, the universe needs operator overloading. :rolleyes:

Jim, I'm sorry, on the line that says "You should organize your classes on disk", should it say, "You should not organize your classes on disk"?

Thank you,

Joe Z.

Link to comment

QUOTE(jzoller @ Oct 3 2007, 11:19 AM)

Obviously, the universe needs operator overloading. :rolleyes:

Jim, I'm sorry, on the line that says "You should organize your classes on disk", should it say, "You should not organize your classes on disk"?

Thank you,

Joe Z.

Joe,

I said that the classes should be stored under a "classes" folder inside subfolders named after the respective class. Isn't this a form of "organization on disk"? It certainly isn't disorganization ;)

Cheers,

-Jim

Link to comment

Thanks Jim,QUOTE(Jim Kring @ Oct 3 2007, 04:37 PM)

i kind of expected classes to behave like libraries, and therefore hold his "domain name". so i tried to directly use my template project folder with just addition of classes, and ended up side down. i was hoping to put several classes in folders related say to 'IO' folder, or 'report' folder. so either i would have to use nested folders, with several "classes" subfolders (which i hate), or find a totally different solution. but then of course the whole point of classes is to have a repository somewhere, that i could pick from when needed. i would then copy the whole class to my project. it forces me to rethink my template folders for as you say changing hierarchy. i need more testing to make up my mind. too bad i just got 2 months ago the 8.2. getting the 8.5 will take here some more time...:(

---------------

Aristos! it is so great to have an insider here in these forums. i have zillion of questions on "how do they really do that". but thats for another time.. :rolleyes: i do recall that in MS Visual studio i could choose to have my project vue by folder, or by class, or full list of methods by name...could we implement same kind of solution here? QUOTE(Aristos Queue @ Oct 3 2007, 05:11 PM)

Any tree can show only a single hierarchy. It is logically impossible for a tree to show multiple indepenent hierarchies. Although
LV
R&D has been working very hard to invalidate the logic of the universe on several key points, at this time, we are unable to circumvent "A == A" and "1 != 0".
:P

i heard there were new string theories around, predicting it will be actually possible :)first we just have to show time reversal, by measuring the electron dipole moment, at a precision better than 10E10-33 (!!), then we will be able to completely discredit Einstein Theory, and finally, accept that the 11 strings are the right one! :DLV team can already work on its implementation :yes:

---------------

QUOTE(Jim Kring @ Oct 3 2007, 04:37 PM)

thats it! i need 8.5! so much easier with the "choose implementation" . i am going to sit tomorow all day at our it desk. this and the stop in for loop...unthinkable without it.

Link to comment
  • 5 months later...

I thought about starting a new thread but somehow I thought the title of this one applied nicely to my question too. So here it is.

I'm trying to use override functions to change the datatype from ancestor to child class. My motivation is that for instrument driver, we sometimes have different types (VISA, strings, IVI, ...) and I would like to have all derive from the same ancestor class (say instruments.lvclass). I was surprised to find out I could not change the datatype. I get the error saying the connector pane should be the same, so I had to go around the problem by using a Variant and all the subsequent dealings associated with that.

I made a simple test using Numeric and Directory in an ancestor class (DBL Numeric + String Directory) for which I override with a Complex Numeric in one case and a Path Directory in the second case. I'd like to know if it is even possible to imagine such a feature working correctly in LVOOP? Why is this diagram giving me a broken arrow? I am not used to OOP in C++ or other languages but I thought it was something possible in C++...

Could that be solved with dynamic dispatch for controls/indicators other than Objects? For the moment, I saw this possibility is grayed out...

By the way, all connector panes are the same, except datatype...

post-10515-1205503435.jpg?width=400

Link to comment

QUOTE (normandinf @ Mar 14 2008, 07:13 AM)

I'd like to know if it is even possible to imagine such a feature working correctly in LVOOP? Why is this diagram giving me a broken arrow?

The short answer (and a jedi like AQ can give all the gory details) is that all the connector panes of a dynamic dispatch VI and its overrides have to be the same because they're constrained by the syntax of G as a language.

To elaborate a little bit... One of the biggest features of LVOOP's dynamic dispatch is that the override VI that is called at a particular node is determined at runtime, but the wire types and their connections (i.e. the complex numeric vs. the filepath) must be determined at edit time. If you had two override VIs with different connector panes both overriding the same dynamic dispatch VI, it would be impossible for the compiler to generate valid code because it doesn't know in advance what class will be on the dynamic dispatch wire.

In a couple rare instances, I've used a Variant as an input to a dynamic dispatch VI just like you mention, but generally I try to avoid the question entirely. I would be interested to know if other people have different approaches.

Link to comment

QUOTE (normandinf @ Mar 14 2008, 09:13 AM)

I'm trying to use override functions to change the datatype from ancestor to child class.

I believe the solution in your situation is

a) Make the output terminal be of the Parent class type and

b) do not make that output terminal "dynamic dispatch output".

The dynamic dispatch input must preserve data type from input to output, and so must be the same class as the input. But a regular output is free to output any value of the output type, which, since the output will be some type of Parent, can be any child type you want to change to.

Is this what you're looking for?

Link to comment

QUOTE (Aristos Queue @ Mar 14 2008, 09:47 AM)

I believe the solution in your situation is

a) Make the output terminal be of the Parent class type and

b) do not make that output terminal "dynamic dispatch output".

Would (b) prevent you from overriding the VI in a grandchild class? I should probably know the answer, but I have not had the chance to work with LVOOP as much as I'd like.

Link to comment

QUOTE (eaolson @ Mar 14 2008, 11:15 AM)

Would (b) prevent you from overriding the VI in a grandchild class? I should probably know the answer, but I have not had the chance to work with LVOOP as much as I'd like.

Yes indeed, it would work if there are no more overrides to be done, which makes it a dead-end for future speciations. In the case I present it would still be a good compromise, since my instrument.model class would most probably be the end of the line (instrument = parent; model = child w/o any possible grandchild)... Which would make it a "sterile class" by not being able to reproduce. :laugh:

Thanks all for your inputs.

Link to comment

QUOTE (eaolson @ Mar 14 2008, 10:15 AM)

Would (b) prevent you from overriding the VI in a grandchild class? I should probably know the answer, but I have not had the chance to work with LVOOP as much as I'd like.

No, it would not. You don't need a dynamic output to override. Only a dynamic input.

Link to comment

In your picture you say:

"Hence, the call will be for parent instead of child"

It will not. What would be the point of dynamic dispatching if it did???

The node you're pointing at is Write Directory.vi, which I'm going to abbreviate as WD.vi for the rest of this post.

WD.vi takes a parent class as input. Child class data can travel on parent class wires. The data that actually goes into WD.vi is *child* data. That means that if the child has an override for WD.vi -- which ClassB1 does -- then the override will be invoked. If the child does not have its own override -- which is the case for ClassB2 -- then the parent implementation will be used. Now, suppose that somewhere on the block diagram of ClassA:WD.vi you make a call to Read Numeric.vi. If the data on the wire is ClassA or ClassB1, then the invoked VI will be ClassA:Read Numeric.vi. But, if the data is ClassB2.vi, then it will invoke ClassB2:Read Numeric.vi.

You object to having to do a To More Specific cast. You should *not* have to do this. If you do, it means something is wrong with your entire design. Here's why:

a) By making the output of the first node not be a dynamic dispatch output, you're saying, "The data coming out of this node might be any of these types. From this point forward, I should only be calling functions that are defined on ClassA." The child classes may override those methods, and the overrides will be invoked, but fundamentally you've said that there's no way to depend upon the specific type of the output.

b) Any time you find yourself in a situation where you must use To More Specific, there is an extremely high probability that there is a problem in your class hierarchy design. Either you need to add another dynamic dispatch method so that the child classes have a chance to specify custom behavior as part of generic algorithms, or you've got something inheriting from something else that really shouldn't be. To More Specific gets used commonly when the class hierarchy is wrong for a given situation, but for some reason you can't change the hierarchy (perhaps because you have to maintain compatibility with some other system, or perhaps the classes are password protected and you don't have the password, or etc).

Link to comment

I think there's still a little confusion about what normandinf is asking.

The reason normandinf has a broken run arrow is because Class A and Class B2 both have a dynamic dispatch method called "Write Numeric.vi" and the connector panes of the two VIs are different.

In Class A, Write Numeric.vi takes a DBL.

In Class B2, Write Numeric.vi takes a CDB (or at least, a complex number of some sort).

This will not work, for the reasons I described in my other reply above.

What normandinf is asking for, in effect, is the ability to override the Private Data of a Parent Class in a Child Class while still using the same dynamic dispatch VIs to read & write that data. :nono:

If I've got this wrong somehow, please post a screenshot of the Errors List window.

Link to comment

QUOTE (Justin Goeres @ Mar 19 2008, 10:49 AM)

What normandinf is asking for, in effect, is the ability to override the Private Data of a Parent Class in a Child Class while still using the same dynamic dispatch VIs to read & write that data. :nono:

Ohhhh. Gotcha. Yes, that is very different.

The solution is to have a parent class that doesn't have the numeric. The parent implements Read/Write Numeric.vi using the narrowest data type -- in this case, double -- but these two VIs do not actually do anything. Then you have two child classes. One of these children has a double and the other has a complex as its private data. You implement Read/Write Numeric on both of these. Now, that only allows you to store double values into the complex field. If you want to use the widest type in the parent -- complex -- then you have to lose data when ever you store into the class that only stores doubles.

Does that make sense?

What are you trying to build?

Link to comment

QUOTE (Aristos Queue @ Mar 19 2008, 03:14 PM)

It was only a theoretical question. I thought I could build a superdriver for instruments I have in my lab, for example something that would call VISA, IVI or AI transparently. But I don't want something more complicated for me than it will be for the user... I think I'm asking for a small change that would have made my life easier in this situation but would inevitably complicate the task of everyone else!!!

QUOTE (Aristos Queue @ Mar 19 2008, 03:14 PM)

Ohhhh. Gotcha. Yes, that is very different.

The solution is to have a parent class that doesn't have the numeric. The parent implements Read/Write Numeric.vi using the narrowest data type -- in this case, double -- but these two VIs do not actually do anything. Then you have two child classes. One of these children has a double and the other has a complex as its private data. You implement Read/Write Numeric on both of these. Now, that only allows you to store double values into the complex field. If you want to use the widest type in the parent -- complex -- then you have to lose data when ever you store into the class that only stores doubles.

Does that make sense?

Well, now it does. I didn't realize I was asking for Private Data Override. Thanks Justin for pointing that out...

In this particular example, I could have the parent class contain a complex number as you suggested: any DBL value I'd wire as an input would be coerced to the form x+i*0, so I wouldn't lose any data/precision. For directory, I'd better use a string than to play around with type overrides.

Link to comment

QUOTE (Aristos Queue @ Mar 19 2008, 03:14 PM)

It was only a theoretical question. I thought I could build a superdriver for instruments I have in my lab, for example something that would call VISA, IVI or AI transparently. But I don't want something more complicated for me than it will be for the user... I think I'm asking for a small change that would have made my life easier in this situation but would inevitably complicate the task of everyone else!!!

QUOTE (Aristos Queue @ Mar 19 2008, 03:14 PM)

Ohhhh. Gotcha. Yes, that is very different.

The solution is to have a parent class that doesn't have the numeric. The parent implements Read/Write Numeric.vi using the narrowest data type -- in this case, double -- but these two VIs do not actually do anything. Then you have two child classes. One of these children has a double and the other has a complex as its private data. You implement Read/Write Numeric on both of these. Now, that only allows you to store double values into the complex field. If you want to use the widest type in the parent -- complex -- then you have to lose data when ever you store into the class that only stores doubles.

Does that make sense?

Well, now it does. I didn't realize I was asking for Private Data Override. Thanks Justin for pointing that out...

In this particular example, I could have the parent class contain a complex number as you suggested: any DBL value I'd wire as an input would be coerced to the form x+i*0, so I wouldn't lose any data/precision. For directory, I'd better use a string than to play around with type overrides.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.