GregFreeman Posted August 20, 2013 Report Share Posted August 20, 2013 (edited) cross posted: http://forums.ni.com/t5/LabVIEW/Compare-parts-of-two-child-objects-and-use-call-parent-method/td-p/2530980 I am trying to validate if two child objects can be grouped together, based on some conditions in their private data. So, I would like to have a "checkIfValid" method in the parent class that has both the settings must override and must call parent method. However, I am running into problems because the connector panes must match. The following VI gives me a broken run arrow. Is there any way to implement what I want? A picture is worth a thousand words so here you go. Is there any way for me to do this comparison, while using DD to force the call parent method? Edited August 20, 2013 by for(imstuck) Quote Link to comment
QueueYueue Posted August 21, 2013 Report Share Posted August 21, 2013 The second StraingChannel Needs to be the same object type as the parent VI. This means that instead of StrainChannel data type, it needs to be ParentOfStrainChannel Data type. My guess is you'll need to cast it to the child data type in the code you screen shotted, or you'll need to figure out another way of doing this. Quote Link to comment
GregFreeman Posted August 21, 2013 Author Report Share Posted August 21, 2013 The second StraingChannel Needs to be the same object type as the parent VI. This means that instead of StrainChannel data type, it needs to be ParentOfStrainChannel Data type. My guess is you'll need to cast it to the child data type in the code you screen shotted, or you'll need to figure out another way of doing this. Yeah, I know I can use to more specific. Was just wondering if I could avoid any run time type checking also. Looks like that may be unavoidable. Quote Link to comment
Popular Post Aristos Queue Posted August 23, 2013 Popular Post Report Share Posted August 23, 2013 Ah, the "double dispatch to compare heterogenous types" problem. An ancient frustration of software developers everywhere. And, worse, I suppose you want the comparison operation to be commutative too (i.e., it doesn't matter which object you put into the top input and which into the bottom input)? a) read this: http://en.wikipedia.org/wiki/Double_dispatchhttp://en.wikipedia.org/wiki/Double_dispatch b) I have never heard of a good solution to this problem in any computer language, but LabVIEW is worse than most because of some limitations on our features -- such as the inability to type cast a VI refnum into any connector pane type *without* LabVIEW type checking it. That kind of "reckless type casting" is a damn fine way to crash any application, but if you can write a system that guarantees (and I mean system-level provable) that all the casts are safe, that's the key to a high performance, low maintenance implementation of such a comparison algorithm. But LabVIEW doesn't generally include "use at your own risk" nodes (the exceptions being Type Cast and Call Library, but even Type Cast has some restrictions which is why it doesn't work for this use case). Even if you had such reckless type casting for VI refnums, this is a hard problem to solve elegantly. I generally recommend that you do the type testing, and either have your own static dispatching through a multilayer maze of case structures or build a 2D dynamic dispatch table of your own. This has an obvious performance hit, even if you implement your own "Get Class Index.vi" that every class overrides to return a unique (but compact sequential over the whole set) integer. There is only pain and suffering down this road if you want to avoid runtime type checking. But it is possible. There are multiple ways to do it. All of them are bad in some way. The Visitor pattern is one you will become very familiar with if you try to do this... lots of variations on the Visitor pattern that all essentially go like this: You create a comparison object that visits the first object to be compared, collects some data then visits the second object and actually does the comparison. You can find endless variations online discussing this problem. One solution that does NOT involve the Visitor pattern is this one... If you know the total set of child classes that will ever exist, this works with high performance but high maintenance burden and lots of VIs: 1. In the ancestor class, create a method "Is Valid.vi" that is dynamic dispatch on the top input. 2. In the ancestor class, create N methods named "Is Valid Assuming First Input is <class name>.vi" where <class name> is the name of a child class. The top input is the child class type. The bottom input is the ancestor type and is dynamic dispatch. Do this for every child class that is not an abstract class. 3. Each child overrides "Is Valid.vi" and uses that VI to wrap a call to "Is Valid Assuming First Input is <class name>.vi", where <class name> is this child class' name. 4. Each child overrides ALL of the methods for "Is Valid Assuming First Input Is <class name>.vi" so that it's type is the bottom type and the other class is the top type. Here you write the actual comparison between these two objects because you now know the exact data type. Oh, but there's a problem... you don't have access to the private data of the other class. So you expose the necessary data accessors to dig into the other class. And you write the comparison. 5. But THEN you take that comparison and you do "Create SubVI From Selection" because you need that exact same comparison in the function on the other class where the top and bottom inputs are flipped. -- end -- This results in a system that is actually quite fast at runtime but is a pain to maintain -- the number of methods in the system expands *geometrically* with the number of concrete child classes. All of this gets even worse if you want to have plug-ins or dynamically loaded classes (the difference being with dynamically loaded classes, you know all the classes ahead of time but you don't want them in memory whereas with plug-ins you don't know the complete set when you write the framework). So far as I know, there is no elegant solution to this problem anywhere in CS. If you find one, please let the world know. 4 Quote Link to comment
GregFreeman Posted August 26, 2013 Author Report Share Posted August 26, 2013 (edited) Mind. Blown. So, awesome, in depth response AQ, but I don't think the benefits outweigh the increased implementation time and potential support of this all. I have stuck it in my back pocket for future reference, but when I sit down and think about the ramifications of a potential incorrect input being wired to the connector pane and getting a run time error vs the implementation time of the above suggestions, I actually feel the right decision is to just deal with and handle a run time error. Of course, there is always the argument that putting in the upfront time can save you run time debugging down the road, but since it sounds like these implementations all have their own potential drawbacks, I'm kind of just picking my poison. Edited August 26, 2013 by for(imstuck) 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.