Function Reference: Difference between revisions
Jump to navigation
Jump to search
m
no edit summary
imported>ZeroMemory (Added a further elaboration on the concept of the "Self" variable.) |
imported>ZeroMemory mNo edit summary |
||
| Line 24: | Line 24: | ||
|style="border-style: solid; border-width: 0"|If you're wondering what is a "Self" variable, it is a natural consequence of object oriented programming which propagates, along with everything else, the concept of a class and an instance of that class, also called an object. A very common example is the difference between a blueprint of a car and the actual car which is made from that blueprint. You can have a bunch of cars based upon a single blueprint. For anything useful, you can't know all the cars that are going to be created from your blueprint, so you need a method of determining upon which object has the function been invoked. And the way this is resolved is by silently pushing in an additional hidden parameter to a function which contains the memory address of the object on which the function is being invoked, of the logical name "Self", because you can't make a change to the data of a class (it's pointless, futile, resistance, Borg... Wait, what?), only the data of an instance of that class. A class is an idea. An object is a manifestation of an idea. A script is an idea. An object it gets appended to, on the other hand, is real (well, virtually real, you get the point). It's a manifestation of that idea. In some languages, '''self''' is called '''this'''. | |style="border-style: solid; border-width: 0"|If you're wondering what is a "Self" variable, it is a natural consequence of object oriented programming which propagates, along with everything else, the concept of a class and an instance of that class, also called an object. A very common example is the difference between a blueprint of a car and the actual car which is made from that blueprint. You can have a bunch of cars based upon a single blueprint. For anything useful, you can't know all the cars that are going to be created from your blueprint, so you need a method of determining upon which object has the function been invoked. And the way this is resolved is by silently pushing in an additional hidden parameter to a function which contains the memory address of the object on which the function is being invoked, of the logical name "Self", because you can't make a change to the data of a class (it's pointless, futile, resistance, Borg... Wait, what?), only the data of an instance of that class. A class is an idea. An object is a manifestation of an idea. A script is an idea. An object it gets appended to, on the other hand, is real (well, virtually real, you get the point). It's a manifestation of that idea. In some languages, '''self''' is called '''this'''. | ||
One could ask: "'''Why should I ever want to use this "Self" variable when I can simply change any variable I want directly, because I know | One could ask: "'''Why should I ever want to use this "Self" variable when I can simply change any variable I want directly, because I know they exist in the blueprint, therefore it's also in the instance. That's the whole point, is it not?'''" True that, young samurai. But here's just a simple example from general programming, imagine that you've got a function invoked on an object (sometimes called a '''non-static member function/method''' or perhaps an '''instance-level member function/method''') that takes a parameter that points to an object of the same class. And you want to make sure you're not being fed the very object the function has been invoked upon. That mouthful is referred to as "self-reference", so you can check whether pObject is equal to self and prevent damaging or unnecessary code from executing. If you can't think of a useful example, it comes in handy with dynamic memory management and functions called setters. | ||
Here, imagine that you are trying to change an object crucial to your application and you want to release the old one because you're a good memory citizen who cares about his users and their limited memory resources. So, you want to first release the old object and then set the pointer to the new one, right? But what if a nasty scenario occurs where you replace the object with itself? You release the old object, set the Self pointer to the memory address of the "new" object (which is, actually, the old object), try to dereference it (a fancy word for "use it") and boom - a wild unicorn appears and destroys your application '''if you're lucky'''. Usually, the memory is just cleared to be overwritten, the system might not use it immediately, therefore, in some cases - your application could work and make your life miserable by reports of crashing. You made a dangling pointer which references an object that was released (by you, a moment ago). Do you, perhaps, see how you could solve this? Yes, exactly. If newObject is NOT equal to Self (newObject != Self), then release the object referenced by Self and change the Self pointer/variable to point to newObject (Self = newObject). And you've solved all of your life's troubles. Kittens are purring. Birds are singing. And gamers are cursing at the dragon that killed them because your game or mod is awesome. | Here, imagine that you are trying to change an object crucial to your application and you want to release the old one because you're a good memory citizen who cares about his users and their limited memory resources. So, you want to first release the old object and then set the pointer to the new one, right? But what if a nasty scenario occurs where you replace the object with itself? You release the old object, set the Self pointer to the memory address of the "new" object (which is, actually, the old object), try to dereference it (a fancy word for "use it") and boom - a wild unicorn appears and destroys your application '''if you're lucky'''. Usually, the memory is just cleared to be overwritten, the system might not use it immediately, therefore, in some cases - your application could work and make your life miserable by reports of crashing. You made a dangling pointer which references an object that was released (by you, a moment ago). Do you, perhaps, see how you could solve this? Yes, exactly. If newObject is NOT equal to Self (newObject != Self), then release the object referenced by Self and change the Self pointer/variable to point to newObject (Self = newObject). And you've solved all of your life's troubles. Kittens are purring. Birds are singing. And gamers are cursing at the dragon that killed them because your game or mod is awesome. | ||