<html><head><META http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Scripted Methods</title></head><body bgcolor="ffffff"><table cellspacing="10"><tr><td align="center"><a href="http://www.beanshell.org/"><img src="../images/homebutton.gif"><br>Home</a></td><td><a href="syntax.html#Basic_Syntax"><img src="../images/backbutton.gif"><br>Back </a></td><td align="center"><a href="contents.html"><img src="../images/upbutton.gif"><br>Contents</a></td><td align="center"><a href="objects.html#Scripted_Objects"><img src="../images/forwardbutton.gif"><br>Next </a></td></tr></table><h1>Scripted Methods</h1> You can define define methods in BeanShell, just as they would appear in Java: <p></p><center><table width="100%" cellpadding="5" border="1"><tr><td bgcolor="#dfdfdc"><pre> int addTwoNumbers( int a, int b ) { return a + b; } </pre></td></tr></table></center><p></p> And you can use them in your scripts just as you would any Java method or "built-in" BeanShell command: <p></p><center><table width="100%" cellpadding="5" border="1"><tr><td bgcolor="#dfdfdc"><pre> sum = addTwoNumbers( 5, 7 ); </pre></td></tr></table></center><p></p> Just as BeanShell variables may be dynamically typed, methods may have dynamic argument and return types. We could, for example, have declared our add() method above like so: <p></p><center><table width="100%" cellpadding="5" border="1"><tr><td bgcolor="#dfdfdc"><pre> add( a, b ) { return a + b; } </pre></td></tr></table></center><p></p> In this case, BeanShell would dynamically determine the types when the method is called and attempt to "do the right thing": <p></p><center><table width="100%" cellpadding="5" border="1"><tr><td bgcolor="#dfdfdc"><pre> foo = add(1, 2); print( foo ); // 3 foo = add("Oh", " baby"); print( foo ); // Oh baby </pre></td></tr></table></center><p></p> In the first case Java performed arithmetic addition on the integers 1 and 2. (By the way, if we had passed in numbers of other types BeanShell would have performed the appropriate numeric promotion and returned the correct Java primitive type.) In the second case BeanShell performed the usual string concatenation for String types and returned a String object. This example is a bit extreme, as there are no other overloaded operators like string concatenation in Java. But it serves to emphasize that BeanShell methods can work with loose types. <p CLEAR="ALL"></p> Methods with unspecified return types may return any type of object (as in the previous example). Alternatively they may also simply issue a "return;" without a value, in which case the effective type of the method is "void" (no type). In either case, the return statement is optional. If the method does not perform an explicit "return" statement and the return type is not explicitly set to void, the value of the last statement or expression in the method body becomes the return value (and must adhere to any declared return typing). <p CLEAR="ALL"></p> <h3>Method Modifiers and 'throws' Clauses</h3> The standard Java modifiers may be applied to methods: private / protected / public, synchronized, final, native, abstract, and static. <p CLEAR="ALL"></p> The synchronized modifier is the only modifier currently implemented. The others are ignored. The 'throws' clause of methods is checked for valid class type names, but is not otherwise enforced. <p CLEAR="ALL"></p> Synchronized methods are synchronized on the object representing the method's common parent scope, so they behave like Java methods contained in a class. We will return to this topic after discussing scripted objects and "closures". <p></p><center><table width="100%" cellpadding="5" border="1"><tr><td bgcolor="#dfdfdc"><pre> // foo() and bar() are synchronized as if they were in a common class synchronized foo() { } synchronized bar() { } </pre></td></tr></table></center><p></p> <h2><a name="Scoping_of_Variables_and_Methods">Scoping of Variables and Methods</a></h2> As in Java, a method can refer to the values of variables and method names from the enclosing scope (in Java the "enclosing scope" would be a class). For example: <p></p><center><table width="100%" cellpadding="5" border="1"><tr><td bgcolor="#dfdfdc"><pre> a = 1; anotherMethod() { ... } foo() { print( a ); a = a+1; anotherMethod(); } // invoke foo() foo(); // prints 1 print( a ); // prints 2 </pre></td></tr></table></center><p></p> Variables and methods are "inherited" from the parent scope in the usual way. In the example above there are just two levels of scope: the top or "global" scope and the scope of the method foo(). Later we'll talk about scripting objects in BeanShell and see that there can be arbitrary levels of scoping involved. But the rules will be the same. <p CLEAR="ALL"></p> As in Java, a typed variable is not visible outside the scope in which it is declared. So declaring a variable with a type is a way to limit its scope or make a <em>local</em> variable. In BeanShell using an untyped or "loosely" typed variable is also equivalent to declaring a local variable. That is, if you use a variable that has not been defined elsewhere, it defaults to the local scope: <p></p><center><table width="100%" cellpadding="5" border="1"><tr><td bgcolor="#dfdfdc"><pre> a = 1; foo() { a = a + 1; // a is defined in parent scope b = 3; // undefined, defaults local scope int c = 4; // declared local scope } // invoke foo() print( a ); // prints 2 print( b ); // ERROR! b undefined print( c ); // ERROR! c undefined </pre></td></tr></table></center><p></p> In the above example the variable 'a' is declared in the global scope. When its value is read and assigned inside of foo() the global value of 'a' will be affected. <p CLEAR="ALL"></p> The variable 'b' is a usage of an untyped variable. Since 'b' has not been declared or assigned a value in any enclosing scope, it becomes a local variable 'b' in the scope of foo. The variable 'c' is explicitly declared (with a type) in the scope of foo() and is therefore, of course, local to foo(). <p CLEAR="ALL"></p> Later we'll see that BeanShell allows arbitrary nesting of methods. If we were to declare another method inside of foo() it could see all of these variables (a, b, and c) as it is also in the scope of foo(). <p CLEAR="ALL"></p> <h3>Scoping of Loosely Typed Variables</h3> As in Java, declaring a variable with a type will always make it local. Even if the variable exists in the outer scope, it will be hidden by the local variable declaration. But what of loosely typed variables? As we've seen, untyped variable usage looks just like an ordinary Java assignment. What do we do if we want to make a local variable with the same name as a global one? One answer would be to resort to declaring the variable with a type. But if we wish to continue working with loosely typed variables in this case we have two options: We can explicitly declare a loosely typed variable with the BeanShell 'var' type. Or we can simply qualify our assignment with the 'this.' qualifier. <p CLEAR="ALL"></p> If you wish to, you can explicitly declare an untyped variable (making it local) using the special type 'var'. e.g. <p></p><center><table width="100%" cellpadding="5" border="1"><tr><td bgcolor="#dfdfdc"><pre> foo() { var a = 1; } foo(); print( a ); // ERROR! a is undefined! </pre></td></tr></table></center><p></p> 'var' is a magic type in BeanShell that represents a loose (untyped) variable. The default value of a variable declared with 'var' is null. <p CLEAR="ALL"></p> Alternately, you can use the scope modifier 'this' to explicitly qualify the variable assignment and make it local. <p></p><center><table width="100%" cellpadding="5" border="1"><tr><td bgcolor="#dfdfdc"><pre> foo() { this.a = 1; } foo(); print( a ); // ERROR! a is undefined! </pre></td></tr></table></center><p></p> In this example we used the modifier 'this' to qualify an untyped variable's scope and make it local. We will explain 'this' and what it means in BeanShell scripted methods in the next section on Scripted Objects. <p CLEAR="ALL"></p> <h2><a name="Scope_Modifier:_'super'">Scope Modifier: 'super'</a></h2> <p CLEAR="ALL"></p> Within a method, it is possible to explicitly qualify a variable or method reference with the identifier 'super' in order to refer to a variable or method defined in an enclosing scope (the scope in which the method is defined or "higher"). e.g. <p></p><center><table width="100%" cellpadding="5" border="1"><tr><td bgcolor="#dfdfdc"><pre> int a = 42; foo() { int a = 97; print( a ); print( super.a ); } foo(); // prints 97, 42 </pre></td></tr></table></center><p></p> As in Java, the 'super' modifiers tells the scoping to begin its search for the variable or method in the parent scope. In the case above, the variable 'a' by default refers to the variable in the local scope. By qualifying 'a' with 'super' we can refer to the variable 'a' in the global scope (the "topmost" scope). <p CLEAR="ALL"></p> So, we've seen that 'super' can be used to refer to the method's parent context. We'll see in the next section how 'this' and 'super' are used in scripting Objects in BeanShell. <p CLEAR="ALL"></p> <table cellspacing="10"><tr><td align="center"><a href="http://www.beanshell.org/"><img src="../images/homebutton.gif"><br>Home</a></td><td><a href="syntax.html#Basic_Syntax"><img src="../images/backbutton.gif"><br>Back </a></td><td align="center"><a href="contents.html"><img src="../images/upbutton.gif"><br>Contents</a></td><td align="center"><a href="objects.html#Scripted_Objects"><img src="../images/forwardbutton.gif"><br>Next </a></td></tr></table></body></html>