Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use Groovy to override a method in a Java class, when that Java class is not instantiated in my code?

I am developing an Eclipse RCP application and I recently started to use Groovy in it. So 99% of my code is still Java.

I read that it is possible to use Groovy to override and add methods to Java classes and I was able to test this by adding a method to the java.lang.String.

But this only works when I use the string in a Groovy class. The overridden method is not considered as being overridden in a Java class.

Here's some code:

/*
 * This is a Java class
 */
public class CTabItem {
   ...
   private API
   ...
   public void setControl(Control control){
       private API
   }
}

/*
 * This is also a Java class
 */
public class Control {
   ...
   private API
   ...
}

/*
 * This is also a Java class
 */
public class OtherClass {
  ...
  private API
  ...
  private void someMethodIDontKnow(){
     Control control = new Control();
     CTabItem tab = new CTabItem();
     tab.setControl(control);
  }
}

/*
 * This is a Groovy class
 */
public class MyViewPart extends org.eclipse.ui.part.ViewPart {
     ....
     public void createPartControl(Composite parent) {
          /* parent (or the parent of parent) is a Control
           which is set somewhere in a CTabItem to which
           I don't get access  */
     }        
}

I need to get the tab from the control. But since it's not me who instantiates MyViewPart, but some private API, I have no access to it. Is there something Groovy could do for me here? Any suggestion or code is welcome. Thank you!

like image 916
Alex Avatar asked Dec 09 '22 16:12

Alex


1 Answers

The short answer is: no, it's not possible if the code creating the object and calling the method is pure Java (i.e., non-Groovy) code. Groovy does its magic by intercepting all method calls on objects (both Java objects and Groovy objects) and using its ExpandoMetaClass to add the behavior. However, it can't change how pure Java code determines which method to call on a pure Java class. To see, run the following sample code:

// UseTheString.java (a pure Java class)
public class UseTheString {
    public static void main(String[] arg) {
        String s = "Hello world";
        System.out.println(s);
        System.out.println(s.substring(1));
        ModifyStringClass.messWithMetaClasses(s);
        System.out.println(s.substring(1));
    }
}

and

// ModifyStringClass.groovy (a Groovy class)
class ModifyStringClass {
    public static messWithMetaClasses(String t) {
        java.lang.String.metaClass.substring = { int n -> "!" }
        println(t.substring(1))
    }
}

You'll get the output:

Hello world
ello world
!
ello world

As you can see, Groovy can override the method on a pure Java object if it is called from other Groovy code, but it can't change how the Java code uses it.

like image 164
Tom Panning Avatar answered Jan 17 '23 21:01

Tom Panning