Gabi1 Posted October 4, 2007 Report Share Posted October 4, 2007 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... Quote Link to comment
Jim Kring Posted October 4, 2007 Report Share Posted October 4, 2007 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 Quote Link to comment
Aristos Queue Posted October 4, 2007 Report Share Posted October 4, 2007 Go, Jim, go! 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". 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. Quote Link to comment
jzoller Posted October 4, 2007 Report Share Posted October 4, 2007 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". Obviously, the universe needs operator overloading. 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. Quote Link to comment
Jim Kring Posted October 4, 2007 Report Share Posted October 4, 2007 QUOTE(jzoller @ Oct 3 2007, 11:19 AM) Obviously, the universe needs operator overloading. 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 Quote Link to comment
jzoller Posted October 4, 2007 Report Share Posted October 4, 2007 Thanks Jim, re-rereading it, the sense of it penetrated. JZ Quote Link to comment
Gabi1 Posted October 4, 2007 Author Report Share Posted October 4, 2007 Thanks Jim,QUOTE(Jim Kring @ Oct 3 2007, 04:37 PM) 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. 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.. 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". 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! LV team can already work on its implementation --------------- QUOTE(Jim Kring @ Oct 3 2007, 04:37 PM) 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 http://eyesonvis.blogspot.com/2007/09/create-accessor-dialog-and-choose.html' target="_blank">this blog article by Christina Rogers -- there is a video of how to use this great new feature. 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. Quote Link to comment
Francois Normandin Posted March 15, 2008 Report Share Posted March 15, 2008 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... Quote Link to comment
Justin Goeres Posted March 15, 2008 Report Share Posted March 15, 2008 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. Quote Link to comment
Aristos Queue Posted March 15, 2008 Report Share Posted March 15, 2008 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? Quote Link to comment
eaolson Posted March 15, 2008 Report Share Posted March 15, 2008 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. Quote Link to comment
Francois Normandin Posted March 15, 2008 Report Share Posted March 15, 2008 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. Quote Link to comment
Aristos Queue Posted March 16, 2008 Report Share Posted March 16, 2008 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. Quote Link to comment
Francois Normandin Posted March 18, 2008 Report Share Posted March 18, 2008 QUOTE (Aristos Queue @ Mar 14 2008, 10: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". 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? I tried what you're describing and it doesn't seem to work. If I wire the Parent type class as the output, I cannot call the child VI anymore as it won't propagate the child class to the next input, however dynamical these inputs. I'd have to cast to a more specific class and that removes the advantage of dynamic dispatch. For now, the only solution I see is to use variants, which is fine if that's the only way... There also the problem that broken arrows are not gone. I'd have to remove inheritance because the connector panes don't match. Yeap, variants will have to do. http://lavag.org/old_files/monthly_03_2008/post-10515-1205762115.jpg' target="_blank"> Quote Link to comment
Aristos Queue Posted March 20, 2008 Report Share Posted March 20, 2008 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). Quote Link to comment
Justin Goeres Posted March 20, 2008 Report Share Posted March 20, 2008 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. If I've got this wrong somehow, please post a screenshot of the Errors List window. Quote Link to comment
Aristos Queue Posted March 20, 2008 Report Share Posted March 20, 2008 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. 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? Quote Link to comment
Francois Normandin Posted March 21, 2008 Report Share Posted March 21, 2008 QUOTE (Aristos Queue @ Mar 19 2008, 03:14 PM) What are you trying to build? 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. Quote Link to comment
Francois Normandin Posted March 21, 2008 Report Share Posted March 21, 2008 QUOTE (Aristos Queue @ Mar 19 2008, 03:14 PM) What are you trying to build? 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. Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.