Home

Back

Contents

Next

Scope Modifiers

Now that we've seen how methods can be nested and treated as objects, we can revisit the topic of variable scope and scope modifiers.

'this', 'super', and 'global'

In the "Scripted Methods" section we described the use of 'super' to refer to a method's parent scope (the scope in which the method is defined). And in the previous section we talked about super's brother 'this', which refers to the current method's scope, allowing us to think of a method scope as an object. Now we can see how these concepts are related. Any method scope, and indeed the 'global' scope, can be thought as an object context. A scripted object can be thought of as encapsulated in a parent scope that determines its "environment" - its inherited variables and methods.

The references 'this', 'super', and 'global' are really the same kind of reference - references to BeanShell method contexts, which can be used as scripted objects. From here on We'll refer to 'this', 'super', 'global', and any other reference to a scripted object context in general as a 'this' type reference.

Note:
If you print a 'this' type reference you'll see what it refers to:
    BeanShell 1.3 - by Pat Niemeyer ([email protected])
    bsh % print( this );
    'this' reference (XThis) to Bsh object: global
    bsh % foo() { print(this); print(super); }
    bsh % foo();
    'this' reference (XThis) to Bsh object: foo
    'this' reference (XThis) to Bsh object: global

The above note shows that the foo() method's 'this' reference is local (named 'foo') and that it's parent is the global scope; the same scope in which foo is defined.

'global'

The scope modifier 'global' allows you to always refer to the top-most scope. In the previous note you can see that the top level script context is called "global" and that it appears again as the 'super' of our foo() method. The global context is always the top scope of the script. It is the global namespace of the current interpreter. Referring to 'super' from the top scope simply returns the same 'global' again.

  global.foo = 42; 

Global variables are not special in any way. Their visibility derives simply from the fact that they are in the topmost scope. However, for those who do not like the idea of qualifying anything with "global". You can always use a more object oriented approach like the following.

// Create a top level object to hold some state
dataholder = object();

foo() {
    ...
    bar() {
        dataholder.value = 42;
    }

    bar();
    print( dataholder.value );
}
    

In the above example we used a global object to hold some state, rather than putting the 'value' variable directly in the global scope.

Tip:
In the above example we used the BeanShell object() command to create an "empty" BeanShell scripted object context in which to hold some data. The object() command is just a standard empty method named object() that returns 'this'. The variable 'dataholder' above is a 'this' type reference and has all of the properties of any other BeanShell object scope.

Synchronized Methods Revisited

Now that we have covered the meaning of 'this' and 'super' with respect to BeanShell methods we can define the meaning of the 'synchronized' modifier for BeanShell methods. Synchronized BeanShell methods behave as if they were in a common class by synchronizing on their common 'super' reference object. For example, in the four cases in the following example, synchronization occurs on the same Java object. That object is the 'this' type reference of the global scope (a Beanshell object of type bsh.This):

print( this ); // 'this' reference (XThis) to Bsh object: global

// The following cases all synchronize on the same lock
synchronized ( this ) { }     // synchronized block
synchronized int foo () { }   // synchronized method foo()
synchronized int bar () { }   // synchronized method bar()
int gee() {
	synchronized( super ) { }  // synchronized blockinside gee() 
}


Home

Back

Contents

Next