<section>
<name filename="objects">Scripted Objects</name>

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.
<p/>

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.
<p/>

<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:
<pre>
    // MyClass.java
    MyClass {
        Object getObject() {
            return this; // return a reference to our object
        }
    }
</pre>

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'.
</note>

<h2>The 'this' reference</h2>

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:

<example>
// Define the foo() method:
foo() {
    int bar = 42;
    print( bar );
}   

// Invoke the foo() method:
foo();  // prints 42

print( bar ); // Error, bar is undefined here 
</example>

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.
<p/>

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.
<p/>

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:

<example>
foo() {
    int bar = 42;
    return this;
}

fooObject = foo();
print( fooObject.bar ); // prints 42!
</example>

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.
<p/>

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:

<example>
foo() {
    bar() {
        ...
    }
}
</example>
Scripted methods may define any number of nested methods in this way, to an 
arbitrary depth.  The methods are "local" to the method invocation.  
<p/>

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:

<example>
foo() {
    int a = 42;
    bar() {
        print("The bar is open!");
    }
    
    bar();
    return this;
}

// Construct the foo object
fooObject = foo();     // prints "the bar is open!"
// Print a variable of the foo object
print ( fooObject.a );  // 42
// Invoke a method on the foo object
fooObject.bar();       // prints "the bar is open!"
</example>
<p/>

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:
<example>
foo() {

	bar() { }

	if ( true ) {
		bar2() { }
	}

	return this;
}
</example>

In the above example the methods bar() and bar2() are both defined within
foo().
<p/>

<p/>
In the next section we'll return to the topic of variable scoping and
go into more depth about how to work with scripted methods and objects.
<p/>

</section>
