LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

LVOOP "call parent method" doesn't work when used in sibling VI

It seems to me that the "call parent method" doesn't work properly according to the description given in the LabVIEW help.

 

I have two basic OOP functions I am doing examples for. I can get one to work easily and the other one is impossible.

 

Background

There are 3 basic situations in which you could use the "call parent method"

 

  1. You are calling the parent VI (or method) of a child VI from within the child VI
  2. You are calling the parent VI (or method) of a child VI from within a sibling VI
  3. You are calling the parent VI (or method) of a child VI from a different class/object.

From the LabVIEW help system for "call parent method":

Calls the nearest ancestor implementation of a class method. You can use the Call Parent Method node only on the block diagram of a member VI that belongs to a class that inherits member VIs from an ancestor class. The child member VI must be a dynamic dispatching member VI and have the same name as the ancestor member VI

 

From my reading of that it means situation 3 is not supported but 1 & 2 should be.

 

Unfortunately only Situation 1 works in LabVIEW 2012.

 

Here is what I want

Reverted Behaviour.lvclass-operation_VI-desired.jpg

 

 

And this is what I actually get

Reverted Behaviour.lvclass-operation_VI-actual.jpg

 

 

What this means is that I can perform a classic "Extend Method" where a child VI will use the parent's implementation to augment it's functions BUT I cannot perform a "Revert Method" where I call the parent method's implementation rather than the one that belongs to the object.

 

If you want a picture

Revert Method PIN.jpg

 

 

Any time I try and make operation2 the VI with the "call parent method" it shows up for about 1/2 sec and then turns into operation.

 

So there are only 3 possibilities I can see

 

  1. Bug
  2. Neither situation 2 or 3 are intended to work (see above) and the help is misleading
  3. I just don't know what I am doing (and I am willing to accept this if someone can explain it to me)

 

The downside is that if situation 2 above doesn't work it does make the "call parent node" much less usefull AND it's usage/application just doesn't make sense. You cannot just drop the "call parent node" on a diagram, it only works if you have an existing VI and you perform a replace. If you can only perform situation 1 (see above) then you should just drop the "call parent node" and it picks up the correct VI as there is only 1 option. Basically if situation 2 is not intended to work then the way you apply "call parent method" doesn't make sense.

 

 

Attachements:

For the really keen I have included 2 zip files

One is the "Revert Method labVIEW project" which is of course not working properly because it wants to "call parent method" on operation not operation2

The other zip file is all pictures with a PIN for both "Revert Method" and "Extend Method" so you can see the subtle but important differences and pictrures of the relavant block diagrams including what NI suggested to me as the original fix for this problem but wasn't (they were suggesting I implement Extend Method).

 

 

 If you are wondering where I got the names, concepts and PIN diagrams from see:

  • Elemental Design Patterns

  • By: Jason McColm Smith

  • Publisher: Addison-Wesley Professional

  • Pub. Date: March 28, 2012

  • Print ISBN-10: 0-321-71192-0

  • Print ISBN-13: 978-0-321-71192-2

  • Web ISBN-10: 0-321-71255-2

  • Web ISBN-13: 978-0-321-71255-4

 

 All the best

 

David

Download All
0 Kudos
Message 1 of 11
(3,816 Views)

Woops!

 

For some reason I managed to include 2 zips of the same images files and didn't include the example project.

 

Hopefully this will have the project files now.

 

All the best

 

David

0 Kudos
Message 2 of 11
(3,801 Views)

I think you have some misconceptions here, so let's clear it up:

 

  1. Only use case 1 is supported. That's what the DD mechanism is supposed to do.  I think the help is fairly clear on that: The child member VI must ... have the same name as the ancestor member VI. Operation 2 has a different name, so it's not covered by this.
  2. I'm not sure why you think that you need to replace a VI to get the call parent node. Just drop the node from the palette and it will automatically call the nearest parent implementation (for the current VI, because it's case 1).
  3. Your description says that you're trying to call only the parent imp (although if that's the case, why do you have the child imp at all?), but you're actually showing that you call some code in the child and then you call another method from the parent. Both use cases are pretty simple to do:

    a) For the first, either don't create the child imp at all or put the child code in a case structure and don't execute it.

    b)For the second, simply call the other VI from the parent class. You don't need to use the call parent method at all.

 

 

 


___________________
Try to take over the world!
Message 3 of 11
(3,783 Views)

Hi tst,

 

Thankyou for your reply. Can you have a look at my comments below on the points you make.

 

1) Have to disagree on that one. The help is unfortunately not clear. The part you quote in your reply only indicates that the VI you are applying "Call Parent Node" to must be dynamic dispatch. There is nowhere in the help it actually states that the call parent node applies to the VI of the block diagram it is placed into. Basically case 2 in my example fulfills all that the help file requires of it. The dynamic dispatch VI's operation are part of a class that inherits from a given ancestor. Operation 2 for Reverted behaviour is a child VI that is dynamic dispatch and has the same name as the ancestor VI (operation2). The help is missing one important piece of information and should be corrected.

 

2) True it does work this way. I was trying to build case 2 and had not yet built my ancestor DD for operation so the function dropped but wasn't associated with any VI. I was able to do this via a replace (obviously once the ancestor Vi was built) so this one is just bad operator

 

3) Keep in mind this is an example not my end goal. I have a child implementation because this is a case where I am trying to do a "reverse override" if you like.

 

3a) The point of the example is to override an objects method (operation2) with it's parent's method NOT it's own. The reason there is a child implementation with specific code is to prove that the parent method is called not the one that relates to the object (child's VI). If I start having to put case structures into the child VI I make the child VI have to determine which code to execute. The point of Revert method is to take this function out of the method that is doing the work. (Single Use Principal and encapsulation)

 

3b) The VI I am calling is a Dynamic Dispatch VI. That means if I drop the superclass's VI onto the child's block diagram it will become the child's implementation. Basically I can't use Dynamic Dispatch in this case at all. It would have to be static. That then means I have to put in additional logic unless there is some way to force a VI to use a particular version of a DD VI (which I can't seem to find).

 

Additional Background

One of the uses for "Revert Method" is in versioning.

 

I have a parent Version1 implementation of something and a child Version2. The child uses Version2 BUT if it fails the error trapping performs a call to Version1.

 

LabVIEW has the possibility of handling the scenario but only if both Case 1 and Case 2 work. It would actually be more useful if all 3 cases worked.

 

The advantage of the call parent method moving one up the tree means I don't have the track what my current object is and choose from a possible list, if, for example the hierarchy is maybe 5 levels deep. (so V4 calls V3 with a simple application of "call parent method" rather than doing additional plumbing with case structures that require care and feeding). Basically the sort of thing OOP is meant to help reduce. Anything that doesn't allow case 2 or 3 means you have to work around the limitation from a software design perspective.

 

If at the end of the day Case 2 and case 3 don't and won't ever work then the help file entry needs to be fixed.

 

 

All the best

 

David

0 Kudos
Message 4 of 11
(3,746 Views)

@dpnsw wrote:
The part you quote in your reply only indicates that the VI you are applying "Call Parent Node" to must be dynamic dispatch.

And that it has to have the same name. Same name = overriding VI and Operation2 has no connection to Operation1. That may not be the best design, but it is what LV uses. The help could probably use an example (and there probably is one linked to from the help file).

 

Cases 2 and 3 don't work and I don't see them being hinted at in the help, but maybe that has to do with your expectations. If you can point out something specific in the help which causes you to think they are supported, then we can probably take it to NI.

 

As for whether or not it will be supported, NI has the idea exchange, where you can add an idea for this, but I will warn you that ideas like these usually take years to happen (if they even happen) and you will want the idea to be very clear to people (which means images and concrete examples) - http://forums.ni.com/t5/LabVIEW-Idea-Exchange/idb-p/labviewideas

 

 

 

I can't say I understood the rest of your post. I have no practical experience with OOP in other languages and I don't know how they handle versioning of methods. LV does have versioning of classes, but that only applies to data (i.e. if you save an object of a class whose version is X and try to load it where the version is X+5, then LV should know how to transform the data correctly).

 

I think that you might have to do what you want with explicit code, but without a concrete example I can understand, I can't offer any actual advice.


___________________
Try to take over the world!
0 Kudos
Message 5 of 11
(3,718 Views)

@dpnsw wrote:

3a) The point of the example is to override an objects method (operation2) with it's parent's method NOT it's own.


Then do not create child.operation2(). No need to call the parent method.


@dpnsw wrote:

I have a parent Version1 implementation of something and a child Version2. The child uses Version2 BUT if it fails the error trapping performs a call to Version1.

LabVIEW has the possibility of handling the scenario but only if both Case 1 and Case 2 work. It would actually be more useful if all 3 cases worked.


When I need to auto-detect the object's version, I iterate through the heirarchy of classes (for-loop, array of objects: parent, child, etc), and only pass the correct object along to the rest of the program.

0 Kudos
Message 6 of 11
(3,706 Views)

@tst wrote:

@dpnsw wrote:
The part you quote in your reply only indicates that the VI you are applying "Call Parent Node" to must be dynamic dispatch.

And that it has to have the same name. Same name = overriding VI and Operation2 has no connection to Operation1. That may not be the best design, but it is what LV uses. The help could probably use an example (and there probably is one linked to from the help file).

 



 

Operation 2 is a dynamic dispatch vi and therefore has the same name under both Reverted and original behaviour. The overriding VI is the one that "call parent method" is applied to. There is no mention in the help that the "call parent method" is using and can only use the VI of the block diagram on which it is dropped. Therefore the help is not clear and should be fixed.

 

0 Kudos
Message 7 of 11
(3,700 Views)

I don't know about you, but what do you think this describes? : "You can use the Call Parent Method node only on the block diagram of a member VI that belongs to a class that inherits member VIs from an ancestor class" and "Calls the nearest ancestor implementation of a class method."

 

I think the help is clear on this matter.

 

But to a solution to your problem, have you tried to cast the child object to its parent before calling the parent vi?
try to use the "To more Generic Class" function. That could force the compiler/run-time engine to use the parents implementation.

0 Kudos
Message 8 of 11
(3,690 Views)

Like dkfire said, the first sentence in the documentation is "Calls the nearest ancestor implementation of a class method". Which method? Well, the one you used the node in and the parent implementation therefore has the same name, just like the part I quoted earlier says: "The child member VI must ... have the same name as the ancestor member VI".

 


@dkfire wrote:

 

But to a solution to your problem, have you tried to cast the child object to its parent before calling the parent vi?
try to use the "To more Generic Class" function. That could force the compiler/run-time engine to use the parents implementation.


That won't work because the DD mechanism checks the type of the actual object on the wire, not the type of the wire itself.


___________________
Try to take over the world!
0 Kudos
Message 9 of 11
(3,685 Views)

tst: you are right, did a small test and it still takes the child implementation.

0 Kudos
Message 10 of 11
(3,679 Views)