Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 12/02/2023 in all areas

  1. It was fixed a view days later (f1 or f2 patch). I actually use the f2 patch (version 21.0.1.f2). edit: bug was in 21.0.1.f1 and fixed in 21.0.1.f2
    1 point
  2. "Preserve Run-Time Class" will CHANGE the type of your object to match that of the selector (The RUN-TIME type of the object is guaranteed to match) whereas "To more specific" will leave it unchanged or return an error (and when it's successful, the EDIT-TIME type changes to match the selector). If the input types of your "Preserve Run-Time Class" do not match exactlym the output object will be different than the input object. This can be very dangerous if you have any references / resources inititalised in the incoming object. What I don't know is how LV retains / removes certain fields of the objects if a type change is required within a tree of inheritance or whether it just returns a default object (I think it's a default object). I only use "èReserve Run-Time Class" within either DD functiona or functions which accept a static Object input but outputs the same type. By wiring the output to "Preserve Run-Time Class" (and knowing that my code should ALWAYS return the same type as the input) LV then autoadapts the output type of the Sub-VI to match the input, even if the VI connectors are not DD. In your example, you would most definitely use "to more specific" rather than "Preserve run-time class". Shane. If your object is a visitor to NI Week: Lets say the inheritance hierarchy is NI Week Visitor -> NI Week Presenter -> Jeff K Right? Jeff K is a presenter and a visitor, but clearly not all visitors are Jeff K. Using "To more Specific" on a Presenter with "Jeff K" as a selector will either allow you access to the Jeff K functionality on the SAME person or it will fail because the person just looked like him but isn't him and we all get to have a laugh. If you use "Preserve Run-Time Class" and the guy isn't actually Jeff K, the function will actually clone Jeff K for you to make sure that the object returned actually IS Jeff K, but because memories and skills are not cloneable, he's pretty much useless to you int hat state. On the other hand, using "Preserve Run-Time Class" on Jeff K (who's presenting himself as a visitor only) ends up being similar to "To more specific Class" as it doesn't actually change the object. So the function "Preserve Run-Time Class" is to be used only when the TYPE of the object being forced is more important than the data contained within.
    1 point
  3. Is there a "right way" (or any way for that matter) to call child class methods on a parent object that was stuffed into a DVR? Like everyone else I've been playing around with DVRs lately, focusing primarily on ways to use object references to simplify various design pattern implementations. Today I identified a behavior that has been giving me fits for weeks. If you create an object reference to a parent object, after dereferencing the parent object there does not appear to be any way to downcast it to a child object or use dynamic dispatching to call child class methods. I built a simple example project with a parent class and a child class to illustrate this. These show a simple implicit downcast and upcast to static dispatch methods. The downcast not working isn't surprising since wiring the parent object directly into a static dispatch child method breaks the wire also. Here I tried explicitly downcasting to the child class before calling the static method. There are no bad wires but the run arrow is broken with the error, "Although you can modify the class object inside a reference, you cannot substitute the class object for another object, even if the object belongs to the same class. This restriction prevents you from changing the data type of the object in the reference." This limitation did surprise me, although I suppose it is consistent--bundling the parent in a cluster and using the in-place structure's unbundle/bundle elements generates a runtime error. The difference is the in-place unbundle/bundle elements can easily be replaced with regular unbundle/bundle nodes. There's no equivalent for DVRs. This is as close as I could come to regular unbundle/bundle nodes when using DVRs The downcast gives me a runtime error. What's really odd is that the downcast works despite the error. If I clear the error the child class correctly updates its private data in the static method and a new object reference is created for the parent. I'm not sure if I'll be able to use this for my purposes but at least it's an avenue to explore. I'm also curious which is the bug: the runtime error or the downcast actually working. I tried several other techniques as well, but I always either got a broken run arrow or a runtime error. Are there other solutions I've missed? Parent-Child DVR.zip
    1 point
  4. The candles are starting to flicker to life... I read that and immediately wondered why the first case causes a broken run arrow and the second doesn't. (Hey, it was in CAPS... it was easy to skip the preceeding sentences.) Then the word "object" in the PRTC context help hit me over the head. From my end user perspective, previous versions of Labview don't make a distinction between classes and objects. (For example, the To More Specific Class prim has 'Target Class' as an input that in reality accepts an object.) Despite my attempts to differentiate between the two when posting, in my head I often use the terms interchangably. I'll have to work hard to change my way of thinking. I'd give you more kudos if I could...
    1 point
  5. Daklu, the style of my writing below is fairly terse and occassionally EMPHATIC. I've done this to emphasize key points that I think you've missed in How Things Work. Some customers in the past have felt I'm insulting them writing this way, but it is the only way I know through the limited text medium to highlight the key points. My only other option is to post just the key bits and leave out a lot of the exposition, but that doesn't seem to be as helpful when communicating. So, please, don't think I'm calling you dumb or being disdainful. I'm trying to teach. The problem is that you're almost right. Customers who are completely off-base are easier to teach because they need the whole lesson. Here, I'm just trying to call out key points, but presenting them in their full context to make sure it's clear what fits where. Throughout the post, refer to the graphic at the end of the post as it may clarify what I'm talking about. Dalku wrote: No. If there is, that's a bug that needs to be reported to NI ASAP. Think about what you just asked for... ignore the DVR part for a moment. You just asked for a PARENT object to invoke a CHILD class method. That cannot ever happen. You cannot pass a parent object directly to a function that takes a child object. The parent object in question IS NOT a child -- the parent object does not have the child's private data, nor does it have all the methods that may have been defined on the child class. For this reason, LV will break the wire if you try to wire a parent wire to a child terminal -- the wire is broken because there are zero situations in which this can successfully execute. You CAN pass a child object to a parent terminal. That is because a child IS an instance of the parent -- it has all the necessary data and methods defined to act as a parent object. What you can do is take a child wire, up cast it to a parent wire and make a Parent DVR out of that. Alternatively, you could take a child wire, make a Child DVR wire, and then upcast that to a Parent DVR wire... these two processes produce the idenitical result: a parent DVR that contains child data. Upcast and downcast DO NOT create new objects EXCEPT when they return an error. The point of a cast is to say, "I have an existing object. Please check that it is this type and approve it to go downstream if it passes this test." You use this only when you need to do something for a specific type of object and you do not have the ability to edit the parent and child classes in order to add the appropriate dynamic dispatch VIs to both. Preserve Run-time Class (PRTC) is the same thing. "Allow this object to pass downstream if it passes this test, otherwise create a new object that does pass the test." The test in this case is "Does the object in have the same TYPE AT RUN TIME as the OBJECT (not the wire) on the target object input?" If the left object is the same or a child class of the center object then there is no error. You will ALMOST NEVER WIRE PRTC WITH A CONSTANT FOR THE CENTER TERMINAL. I would say "never" because I can't think of any useful cases, but maybe someone has something out there. If you are wiring the center terminal of PRTC with a constant, something is wrong in your code. You use the PRTC to assert that the left object, which comes from some mystical source, is the right type to fulfill run-time type requirements of dynamic dispatch VIs, automatic downcast static VIs, and the Lock/Unlock of Data Value References. In all three of these cases, there is some input (either the input FPTerm or the left side of the Inplace Elt Struct) that must be passed across to the output (either the output FPTerm or the right side of the Inplace Elt Struct) WITHOUT PASSING THROUGH ANY FUNCTION THAT CHANGES THE OBJECT'S TYPE. You're free to change the object's value, but not its type. Sometimes you pass the object to functions where LV cannot prove that the type is maintained. Easy example -- pass the object into a Global VI and then read the Global VI. You'd never do this, of course, but it demonstrates the problem. LV cannot know that the object you read from the global is the same object you wrote in -- some other VI elsewhere might have written to the global in parallel. But you, as the programmer, know that there are no other writes to the global VI, so you use the PRTC to assert "this is going to be the right object type." You wire the original input (as described above) to the center terminal, and the output of the global to the left terminal, and pass the result to the original output terminal (as described above). Does that make sense?
    1 point
×
×
  • Create New...

Important Information

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