You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Stian Soiland-Reyes edited this page Feb 2, 2016
·
2 revisions
Many people who use BeanShell use it to write scripts that
work with existing Java classes and APIs, or perform other kinds of dynamic
activities for their own applications at run-time without the aid of a
compiler. Often this means writing relatively unstructured code -
for example, a sequence of method invocations or loops, all contained in a
single script file or eval() statement.
In the previous section we saw that BeanShell is also capable of scripting
methods, just like Java. Creating methods and new BeanShell commands
(which are just methods in their own files) is the
natural progression of organizing your scripts into re-usable and
maintainable components.
Beyond methods and structured programming lie, of course, objects and the
full breadth of object oriented programming. In Java objects are the products
of classes. While BeanShell is compatible with standard Java syntax for
statements, expressions, and methods, you can't yet script new Java classes
within BeanShell.
Instead, BeanShell allows you to script objects as "method closures",
similar to the way it is done in Perl 5.x, JavaScript, and other object-capable
scripting languages. This style of scripting objects (which we'll describe
momentarily) is simple and flows very naturally from the style of scripting
methods. The syntax, as you'll see, is a straightforward extension of the
standard Java concept of referring to an object with a 'this' reference.
Note:
In standard Java, a method inside of an object (an instance method) may refer
to the enclosing object using the special variable 'this'. For example:
// MyClass.java
MyClass {
Object getObject() {
return this; // return a reference to our object
}
}
In the example above, the getObject() method of MyClass returns a reference
to its own object instance (an instance of the MyClass object) using this.
The 'this' reference
As in most languages, an executing method in BeanShell has its own
"local" scope that holds argument (parameter) variables and locally declared variables. For
example, in the following code segment any variables that we might use within
the foo() method will normally only be visible within the scope of foo() and
for the lifetime of one particular foo() method invocation:
// Define the foo() method:foo() {
intbar = 42;
print( bar );
}
// Invoke the foo() method:foo(); // prints 42print( bar ); // Error, bar is undefined here
In the above, the bar variable is local to foo() and therefore not available
outside of the method invocation - it is thrown away when the method exits,
just like a standard Java local variable.
Now comes the twist - In BeanShell you have the option to "hang on" to the
scope of a method invocation after exiting the method by referring to the
special 'this' reference. As in Java, 'this' refers to the current object
context. The only difference is that in this case the context is associated
with the method and not a class instance.
By saving the 'this' reference after the method returns, you can continue to
refer to variables defined within the method, using the standard Java "."
notation:
In the above, the value returned by the foo() method (the 'this' reference)
can be thought of as an instance of a "foo" object. Each foo() method
invocation effectively creates a new object; foo() is now not just a method,
but a kind of object constructor.
In the above case our foo object is not so much an object, but really more of a
structure. It contains variables (bar) but no "behavior". The next twist
that we'll introduce is that BeanShell methods are also allowed to contain
other methods:
foo() {
bar() {
...
}
}
Scripted methods may define any number of nested methods in this way, to an
arbitrary depth. The methods are "local" to the method invocation.
Statements and expressions within the enclosing BeanShell method can call
their "local" methods just like any other method. (Locally declared methods
override outer-more methods like local variables hide instance variables in
Java.) The enclosed methods are not directly visible outside of their
enclosing method. However, as you might expect, we can invoke them as we
would on a Java object, through an appropriate object reference:
foo() {
inta = 42;
bar() {
print("The bar is open!");
}
bar();
returnthis;
}
// Construct the foo objectfooObject = foo(); // prints "the bar is open!"// Print a variable of the foo objectprint ( fooObject.a ); // 42// Invoke a method on the foo objectfooObject.bar(); // prints "the bar is open!"
Methods declared inside block structures within methods behave just as if they
were declared directly in the method. i.e. there are no block-local methods.
For example: