BeanShell has a few advanced features that we haven't mentioned yet. They will be discussed in this section.
We noted earlier that BeanShell syntax does not require that
variables be declared or defined with their type, and that variables
that are not typed when first used can have values of differing
types assigned to them. In addition to this “loose”
syntax, BeanShell allows a “convenience” syntax for
dealing with the properties of JavaBeans. They may be accessed or
set as if they were data members. They may also be accessed using
the name of the property enclosed in quotation marks and curly
brackets. For example, the following statement are all equivalent,
assuming btn
is a JButton
instance:
b.setText("Choose"); b.text = "Choose"; b{"text"} = "Choose";
The last form can also be used to access a key-value pair of a
Hashtable
object.
BeanShell uses special keywords to refer to variables or methods defined in the current or an enclosing block's scope:
The keyword this
refers to the
current scope.
The keyword super
refers to the
immediately enclosing scope.
The keyword global
refers to the
top-level scope of the macro script.
The following script illustrates the use of these keywords:
a = "top\n"; foo() { a = "middle\n"; bar() { a = "bottom\n"; textArea.setSelectedText(global.a); textArea.setSelectedText(super.a); // equivalent to textArea.setSelectedText(this.a): textArea.setSelectedText(a); } bar(); } foo();
When the script is run, the following text is inserted in the current buffer:
top middle bottom
As discussed in the macro example in Chapter 14, A Dialog-Based Macro, scripted objects can implicitly implement
Java interfaces such as ActionListener
. For
example:
myRunnable() { run() { System.out.println("Hello world!"); } return this; } Runnable r = myRunnable(); new Thread(r).start();
Frequently it will not be necessary to implement all of the
methods of a particular interface in order to specify the behavior
of a scripted object. To prevent BeanShell from throwing exceptions
for missing interface methods, implement the
invoke()
method, which is called when an
undefined method is invoked on a scripted object. Typically, the
implementation of this method will do nothing, as in the following
example:
invoke(method, args) {}
In addition to the implicit interface definitions described above, BeanShell permits full-blown classes to be defined. Indeed, almost any Java class definition should work in BeanShell:
class Cons { // Long-live LISP! Object car; Object cdr; rplaca(Object car) { this.car = car; } rplacd(Object cdr) { this.cdr = cdr; } }