Consider a Java hierarchy like this:
public interface Copyable {
Copyable copy();
}
public class CopyableBase implements Copyable {
@Override public CopyableBase copy() {
return new CopyableBase();
}
}
public class CopyableParent extends CopyableBase {
@Override public CopyableParent copy() {
return new CopyableParent();
}
}
public class CopyableChild extends CopyableParent {
@Override public CopyableChild copy() {
return new CopyableChild();
}
}
If you execute this code in Jython:
cc = CopyableChild()
copy = cc.copy()
the PyReflectedFunction object to call the copy() method is built with the CopyableParent's version of copy(), not with the CopyableChild's version, which should be preferred as it overrides the parent's one.
This does not cause any trouble in the vast majority of the cases, even in this example: java.lang.reflect.Method.invoke() repairs it by calling the child's version, even if the parent's one is asked to be executed.
However, in a specific case of a much more complex hierarchy, Jython keeps choosing the wrong method, but Method.invoke() is not able to repair it for some reason, and the parent's method is called, thus breaking Java polymorphism.
It can be fixed by commenting out the following lines of org.python.core.ReflectedArgs.compareTo:
// For static methods, use the child's version
// For instance methods, use the parent's version
if (!this.isStatic) {
replace = !replace;
}
Patching jython.jar by skipping this "if" solves the issue in our project; however it should be ammended in future Jython versions too.