-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmethods.html
360 lines (312 loc) · 9.96 KB
/
methods.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
<?xml version="1.0" encoding="UTF-8"?>
<html>
<head>
<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.png" /><br />Home</a>
</td>
<td><a href="syntax.html#Basic_Syntax"><img src="images/backbutton.png" /><br />Back
</a></td>
<td align="center"><a href="contents.html"><img src="images/upbutton.png" /><br />Contents</a></td>
<td align="center"><a href="objects.html#Scripted_Objects"><img
src="images/forwardbutton.png" /><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 />
<center>
<table border="1" cellpadding="5" width="100%">
<tr>
<td bgcolor="#dfdfdc">
<pre>
int addTwoNumbers( int a, int b ) {
return a + b;
}
</pre>
</td>
</tr>
</table>
</center>
<p />
And you can use them in your scripts just as you would any Java method or
"built-in" BeanShell command:
<p />
<center>
<table border="1" cellpadding="5" width="100%">
<tr>
<td bgcolor="#dfdfdc">
<pre>
sum = addTwoNumbers( 5, 7 );
</pre>
</td>
</tr>
</table>
</center>
<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 />
<center>
<table border="1" cellpadding="5" width="100%">
<tr>
<td bgcolor="#dfdfdc">
<pre>
add( a, b ) {
return a + b;
}
</pre>
</td>
</tr>
</table>
</center>
<p />
In this case, BeanShell would dynamically determine the types when the method is
called and attempt to "do the right thing":
<p />
<center>
<table border="1" cellpadding="5" width="100%">
<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 />
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" />
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" />
<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" />
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" />
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 />
<center>
<table border="1" cellpadding="5" width="100%">
<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 />
<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 />
<center>
<table border="1" cellpadding="5" width="100%">
<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 />
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" />
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 />
<center>
<table border="1" cellpadding="5" width="100%">
<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 />
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" />
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" />
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" />
<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" />
If you wish to, you can explicitly declare an untyped variable
(making it local) using the special type 'var'. e.g.
<p />
<center>
<table border="1" cellpadding="5" width="100%">
<tr>
<td bgcolor="#dfdfdc">
<pre>
foo() {
var a = 1;
}
foo();
print( a ); // ERROR! a is undefined!
</pre>
</td>
</tr>
</table>
</center>
<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" />
Alternately, you can use the scope modifier 'this' to explicitly qualify the
variable assignment and make it local.
<p />
<center>
<table border="1" cellpadding="5" width="100%">
<tr>
<td bgcolor="#dfdfdc">
<pre>
foo() {
this.a = 1;
}
foo();
print( a ); // ERROR! a is undefined!
</pre>
</td>
</tr>
</table>
</center>
<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" />
<h2><a name="Scope_Modifier:_'super'">Scope Modifier: 'super'</a></h2>
<p CLEAR="ALL" />
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 />
<center>
<table border="1" cellpadding="5" width="100%">
<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 />
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" />
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" />
<table cellspacing="10">
<tr>
<td align="center"><a href="http://www.beanshell.org/"><img src="images/homebutton.png" /><br />Home</a>
</td>
<td><a href="syntax.html#Basic_Syntax"><img src="images/backbutton.png" /><br />Back
</a></td>
<td align="center"><a href="contents.html"><img src="images/upbutton.png" /><br />Contents</a></td>
<td align="center"><a href="objects.html#Scripted_Objects"><img
src="images/forwardbutton.png" /><br />Next
</a></td>
</tr>
</table>
</body>
</html>