TALES of the VALIANT
  1. #1
    Varsuuk's Avatar
    Join Date
    Dec 2015
    Location
    New York
    Posts
    2,117

    Basic "self/Namespace/super" question

    I saw in Core/invitem where the handler for onDelete being registered was changed to self.onDelete. I have been playing for a bit but mainly in the style of looking at existing code and extrapolating, inferring how things are done. I am always WTF'ed when I try to google "lua when to use self" type questions cos of the examples with metatables colon and non-colon callls (ie syntactic sugar stuff) - I never use scripting languages other than bash mainly to start other apps or pass admin command; but I am very familiar with OOP in C++, Java as well as older languages.

    So... "self" - this means the particular instance. Does that mean when you call self.onDelete it will always call the onDelete defined in that script. But calling without the self could call onDelete from a super class? So in that addHandler you are just being safe so that it will complain if you don't have onDelete defined or is it something else?

    Then there is using the "namespace name" (terms again - like CharManager) - going by my C++/Java experience, I always assumed you are "locking" the call to the global methods in that namespace only. Like if you are writing a line of code in CharManager and do "CharManager.foo()" then it always calls the foo() in CHARMANAGER, even if CharManager is somehow "super" to a class that has "foo()" also defined. And that without CharManager part of the call it would then "find" that foo() instead. I am sure I am being more confusing than now in my question - I do better speaking since can pick up cues and adjust...

    Any nuance or pointing to a forum thread is appreciated. I recall seeing these types of posts early on years ago. I expect many new people ask at least flavors of this. But searching on "self" for example gets too many hits and fails to execute. Even a decent "search term" would be all I need.

    Thanks.


    PS - "super" is at least clear and I get how "self" works with the colon calling (which is what usually returns in my searches) as the first argument etc. I mean "self" in explicit calls.

  2. #2
    "self" is defined for every FG scriptable object (control, window, etc.) This is how you ensure that you are always calling the outermost version of a function; because self always refers to the final object. Since scripts can be nested, function calls within a script only call the local version in the current script or anything defined previously in a script; it can not call future overrides. By changing script calls to self.fn, then that allows future community modders to change a function without having to rewrite the entire script.
    (For global scripts, you'll see that they often use the global script name to make any internal function calls for the same reason.)

    "super" is defined if an object contains more than one script. If no super is defined, there is no previous script defined.

    Regards,
    JPG

  3. #3
    Varsuuk's Avatar
    Join Date
    Dec 2015
    Location
    New York
    Posts
    2,117
    Gotcha - I had forgotten and thought it was the opposite.

    So in my terms, "self" calls is like in C++ calling a function through a pointer. If someone further derived from you, they can override your behavior (of course they can call back with super if they just want to decorate your behavior.) So, self means the function MUST be defined in the script (and cannot be local) but it MAY be later redefined and you will call the most-derived version depending on the eventual object involved in the call.

    When calling with no special qualification - just the function name, then it calls only the function defined in the script or a super version if you don't have one defined in this script. It never cares if it is a base "class" (sorry don't know the words for lua scripts) or the final one - it calls just the version inside itself if there is one.

    Super was always pretty clear.

    When I copied some "locally only" used utility functions or wrote my own - I tended to make them local so that I could bunch the "normal" (global) methods together as an "API" of sorts. MY thing is not a framework and no one will derive from me, if ever that were possible, I'd revisit to "free up" a couple of them. But for now, it helps me "see" the API as a newbie better. If one of the functions had general purpose outside of the script I'd either make it global or move it to a better home. It's the old issue with wanting to make things look like stuff you are used to. Generally a mistake, but one that is helping me more atm than hurting

    But now that I understand my self (see what I did there) better, I will look for places it makes sense to use self for such functionality. In C++ I often used the non-virtual-interfect thing (forgot the real gimmick name/acronym) where I had public non virtual functions and defined protected virtual functions so I could "control" how people used the overrides and ensure some things were always part of the call for stability. I've seen some similar use here with empty callbacks meant to be overridden but are used by functions not likely to be overriden in Core and I dig that.

  4. #4
    I recommend using self or namespace for every internal function call.

    Extension developers will otherwise redefine whole swaths of code in order to override a single function; and that causes things to be even more fragile when you need to make changes later to a function they override but wouldn’t have needed to if self used.

    Regards,
    JPG

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
DICE PACKS BUNDLE

Log in

Log in