#1113 type mismatch while overriding java interface

swined Mon 7 Jun 2010

when trying to compile the following code, compiler complains that types do not match.

using [java]java.util::List as JList 

abstract class Foo : JList 
{ 

  // Type mismatch in override of '[java]java.util::List.size' - '[java]::int' != 'sys::Int' 

  override Int size := 0 

} 

however, if the field is replaced with a method (Int size() { 0 }), everything is ok. it looks like the compiler does not infer types properly in that case. i've made a simple patch to compilerJava that seems to fix the problem:

diff -Nawur compilerJava.old/fan/JavaBridge.fan compilerJava/fan/JavaBridge.fan
--- compilerJava.old/fan/JavaBridge.fan       2010-05-13 09:42:40.000000000 +0700
+++ compilerJava/fan/JavaBridge.fan   2010-06-07 21:03:55.000000000 +0700
@@ -240,6 +240,10 @@
     // route to method override checking
     if (base is JavaMethod && def is MethodDef)
       checkMethodOverride(t, base, def)
+
+    if (base is JavaMethod && def is FieldDef)
+      checkFieldOverride(t, base, def)
+    
   }

   **
@@ -286,6 +290,14 @@
     }
   }

+  private Void checkFieldOverride(TypeDef t, JavaMethod base, FieldDef def)
+  {
+    if (isOverrideInferredType(base.returnType, def.fieldType))
+    {
+      base.returnType = def.fieldType
+    }
+  }
+  
   **
   ** When overriding a Java method check if the base type is
   ** is a Java primitive or array and the override definition is

brian Tue 8 Jun 2010

Promoted to ticket #1113 and assigned to brian

brian Thu 9 Sep 2010

Ticket cancelled

I spent some time this afternoon really digging into this issue (sorry it took so long). In Fantom we allow you to override a virtual method with a field (assuming the method has no parameters). In this case, the method in question uses a Java primitive type so we have to do special magic for coercion of int to sys::Int (which is really java.lang.Long).

But in the case of a field, this means we have to do something with the storage location and the setter too. We could change both to int, but this requires quite a bit of compiler magic. But if we leave the getter as int and the setter/storage as sys::Int then that has its own consequences.

Due to the complexity of this solution and all the boundary conditions its creates, I don't think we should support this feature. At least for now, we can always add it a later date without breaking compatibility. The simple workaround is to do it "Java-style" and override the method with a normal method and create a separate field.

Login or Signup to reply.