From: Leo S. M. <leo...@gm...> - 2008-07-31 20:53:03
|
[CC-ing jython-dev because I think this is interesting...] On Fri, Jul 11, 2008 at 1:02 PM, David Huebel <dav...@gm...> wrote: > On Fri, Jul 11, 2008 at 11:35 AM, Jeff Emanuel <jem...@fr...> wrote: > > On Fri, Jul 11, 2008 at 12:18 PM, Brian O'Neill <bo...@cc...> wrote: > > > Hi, > > > > > > I have a Java class foo that has two constructors: > > > foo(int, int) > > > foo(int, boolean) > > > > > > How do I call the (int, boolean) constructor from Jython? When I use foo(8, > > > 1) and foo(8, java.lang.Boolean.TRUE), it goes to the (int, int) > > > constructor. Any ideas? > > > > Try (8,Boolean(1)) > > I tested this because I was sure it wouldn't work, but it does. > Jython treats Boolean.TRUE differently from other Boolean instances: > >>>> b1 = Boolean.TRUE >>>> b1 > 1 >>>> b2 = Boolean(1) >>>> b2 > true Ugh. I've found that the cause. First, what we all know: Jython translates "java values" to "python values" for every return value of java methods. The mapping is more or less obvious: Integer -> int String -> str Boolean -> bool ... otherwise-> javainstance Where javainstance is a thin wrapper for "generic" objects. So this means that any java method returning a `Boolean` gets it's result transformed to a python's `bool`. Now the cause. The transformation described above is _not_ done for constructors. Constructor "return values" (i.e. `this`) is directly mapped to `javainstance`: >>> type(Boolean(1)) <type 'javainstance'> >>> type(Boolean.TRUE) <type 'bool'> >>> type(Integer(1)) <type 'javainstance'> >>> type(String("foo")) <type 'javainstance'> Bottom line: Jython gives special treatment to Boolean() constructor (and Integer(), Short(), String(), ...) > Is this on purpose, or is it an implementation accident? I'd say it is an accident, but could be convinced otherwise. That's why I'm cc-ing jython-dev here. To me, it has no sense. It is a weird exception to a rule and can cause problems to people registering their own ExtensiblePyObjectAdapter for java -> python translation. On the other hand, looks like what is suggested on this thread is the only way to _ensure_ that the method foo(int, boolean) will be called, even on Jython2.5 where python bool is translated to Java Boolean by default. The problem is that, for java method calling Jython tries to coerce python args to the java classes specified on the all the signatures of the same method name with the same number of arguments, until a successful coercion of all arguments if found. With enough bad luck, the lookup will start by the the foo(int, int), and it will be successful, because PyBoolean still can be coerced to Integer if asked (it's just not the "default" conversion now). I don't think we can do anything here, `bool` in python is a subclass of `int`, thus the behavior is sound. Yet another bottom line: Making java constructor return values behave like they do on java methods (for consistency reasons) will kill this use case. So we can't do it without solving this other problem first. Thoughts? -- Leo Soto M. http://blog.leosoto.com |