FlightGear Newsletter July 2014: Difference between revisions

Jump to navigation Jump to search
m
m (Added link to the Nasal syntax highlighting wiki page under the Notepad++ section)
Line 245: Line 245:
   }}
   }}
}}
}}
=== Nasal: Making safer base-class calls ===
There's a lot of Nasal code floating around doing the equivalent of this when using multiple inheritance to make base class calls:
<syntaxhighlight lang="nasal">
object.parents[x].method();
</syntaxhighlight>
Internally, this works such that Nasal's inheritance mechanism relies on a so called '''parents''' vector that contains a list of classes that are used for field/method look-ups. This vector can be accessed using numeric indexes - thus, the correct value for '''x''' is directly affected by the way the parents vector is set up, i.e. its internal class ordering:
<syntaxhighlight lang="nasal">
var myClass = {parents:[FirstBaseClass, SecondBaseClass, ThirdBaseClass] };
</syntaxhighlight>
However, this practice of using indexed parents access to look up a base class should be considered a "hack" and discouraged, because it's not a particularly robust or even safe way to call a superclass, simply because it doesn't tell Nasal anything about the name of the class you're trying to call, but merely its index in the inheritance/lookup vector, which may be subject to change (e.g. due to refactoring). Thus, we encourage people to actually use Nasal's built-in '''call()''' API to accomplish the same thing in a more robust fashion:
<syntaxhighlight lang="nasal">
call(Class.method, [], me);
</syntaxhighlight>
This will tell Nasal that you want it to call a certain method in a particular class - and if that fails, you'll get better diagnostics (error messages), too. The main problem here is that the other approach is pretty vulnerable when restructuring your code, as it is heavily reliant on inheritance '''ordering''' - which is something that isn't exactly straightforward: code shouldn't "break" just because the inheritance ordering is modified. Thus, please try to use the latter idiom. If in doubt, just get in touch via the Nasal sub forum.
To pass argument to the method, just add them to the 2nd argument, i.e. the empty vector:
<syntaxhighlight lang="nasal">
call(Class.method, [nil,nil,nil], me);
</syntaxhighlight>
To pass a custom namespace environment, you can use this:
<syntaxhighlight lang="nasal">
var namespace = {};
call(Class.method, [nil,nil,nil], me, namespace);
</syntaxhighlight>
Which would be equivalent to this example using an anonymous namespace:
<syntaxhighlight lang="nasal">
call(Class.method, [nil,nil,nil], me, {} );
</syntaxhighlight>
(If you want to preserve/modify the namespace, it makes sense not use an anonymous namespace though).
To do exception handling, you can pass an empty vector and check its size (>=1):
<syntaxhighlight lang="nasal">
var err = [];
call(Class.method, [nil,nil,nil], me, {}, err );
if(size(errors))
print("There was some problem calling a base class method: Class.method()");
</syntaxhighlight>
You can also declare the variable expression inline:
<syntaxhighlight lang="nasal">
call(Class.method, [nil,nil,nil], me, var ns={}, var err=[] );
if(size(errors))
print("There was some problem calling a base class method: Class.method()");
else {
print("Success, namespace is:");
debug.dump(ns);
}
</syntaxhighlight>


== FGCamera ==
== FGCamera ==

Navigation menu