|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 4 of 5
As previously mentioned, dynamically typed languages don't require type declarations. The downside of this convenience is the hidden trap of calling overloaded Java methods. When calling an overloaded Java method, the scripting runtime has to choose the proper one. Under some circumstances the selected method implementation isn't the expected one, as shown in the next two examples.
Listing 8 shows an overloaded Java class.
package test;
public class NonBlockingConnection {
public void write(int i) {
System.out.println("writing int " + i);
}
public void write(long l) {
System.out.println("writing long " + l);
}
}
Listing 9 shows how Jython would call these overloaded methods.
from java.lang import Integer
from test import NonBlockingConnection
# call 1
NonBlockingConnection().write (214748364700) # call method based on python built-in data type
# prints out:
# writing long 214748364700
# call 2
NonBlockingConnection().write (55) # call method based on python built-in data type
# prints out:
# writing long 55
# ups, not int?
# call 3
NonBlockingConnection().write (Integer(55)) # pass over a Java object instead of python data type
# prints out:
# writing int 55
Call 2 of the Jython script doesn't perform the expected int-typed Java method. A practical solution to determine the overloaded method is to instantiate the desired Java data type object
within the script and to pass it over instead of the scripting-internal type. When you use Groovy, method overloading is a
non-issue because Groovy supports both static and dynamic typing.
You can execute scripts within the Java environment by using a script engine. Typically, such script engines also allow you
to perform dedicated scripting methods or functions. JSR 223 defines a standard interface Invokable to perform such methods and functions. As you can see in Listing 10, a dedicated function write of the Ruby script will be called.
String rubyScript = "def write(msg) \r\n" +
" puts msg \r\n" +
"end \r\n" +
"\r\n" +
" def anotherFunction() \r\n" +
" # do something \r\n" +
"end \r\n";
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
engine.eval(rubyScript);
Invocable inv = (Invocable) engine;
inv.invokeFunction("write", new Object[] { "hello" });
// prints out:
// hello
Some scripting environments such as Jython also support a compiler to produce Java classes. In this case a Jython class can be called like a normal Java class. Only the introspection capability of the generated Java class is limited.
JRuby and Jython both have support for implementing Java interfaces as well as extending Java classes. But overwriting overloaded Java method brings in new issues for most popular scripting languages. How to define which overloaded Java method should be overridden? Languages such as Python 2.x or Ruby don't support method overloading based on type signatures. This requires handling all overloaded cases of the overridden method. The method implementation has to dispatch all overload cases by introspecting the argument types. Listing 11 shows how to do this using Jython.
from test import NonBlockingConnection
from java.lang import Integer
from java.lang import Long
class ExtendedNonBlockingConnection(NonBlockingConnection):
def write(self, *args):
# the signature to handle?
if len(args) == 1 and isinstance(args[0], Integer):
print 'writing overriden int ' + args[0].toString()
# no, let the super method do the stuff
else:
NonBlockingConnection.write(self, *args)
ExtendedNonBlockingConnection().write(Integer(777))
# prints out:
# writing overridden int 777
ExtendedNonBlockingConnection().write(Long(777))
# prints out:
# writing long 777
Because Groovy also supports static type declaration the overloaded method can be declared by the argument types in the override method signature, as shown in Listing 12.
import test.NonBlockingConnection
class ExtendedNonBlockingConnection extends NonBlockingConnection {
// overwrite the int method
def write(int i) {
println 'writing overridden int ' + i
}
}
new ExtendedNonBlockingConnection().write((int) 777)
// prints out:
// writing overridden int 777
new ExtendedNonBlockingConnection().write((long) 777)
// prints out:
// writing long 777
Archived Discussions (Read only)