After doing some deeper investigation, I think I know what the problem is. When you write something like:
GluScriptInterface p = (GluScriptInterface) parent.script
// Cannot cast object 'org.acme.parent.GluScriptParent@6a790041' with class 'org.acme.parent.GluScriptParent' to class 'org.acme.common.GluScriptInterface'
it does not work because each script is loaded in its own independent class loader. So the GluScriptInterface loaded by the child is unfortunately a different interface than the GluScriptInterface loaded by the parent (this is how java works... 2 classes are only the same class if they are loaded by the same class loader). The error message is obviously confusing because it seems that they are the same class but because of different class loaders they are not.
GluScriptInterface p = parent.script as GluScriptInterface
will not work either because (this was my misunderstanding) it does not create a dynamic proxy unless it is a map or a closure. In this case it is equivalent to the first call and you end up with the same result.
If you want a partial solution, you actually need a dynamic proxy something like this:
What this does is actually create a dynamic proxy using the GluScriptInterface from the child and delegate all methods to parent.script using groovy dynamic method invocation. Note that this will NOT work for overloaded method (same name for methods with different parameters) unless you add the proper handling in ih closure.
I thought there was an easier way to do this in groovy. Maybe there is that I am not aware of.