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 13, scripted objects can implement Java interfaces such as ActionListener. Which interfaces may be implemented varies depending upon the version of the Java runtime environment being used. If running under Java 1.1 or 1.2, BeanShell objects can only implement the AWT or Swing event listener interfaces contained in the java.awt.event and javax.swing.event packages, along with the java.lang.Runnable interface. If BeanShell is running under Java 1.3 or 1.4, which jEdit 4.0 requires, any interface can be implemented.
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. Under Java 1.3 and above, the virtual machine's reflection mechanism will throw an exception for any missing interface methods. This will bring macro execution to a halt unless the exception is trapped and handled. The solution is to 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) {} |