0

A service from external API which I am not allowed to modify returns me

  MyClass instance = ServiceUtil.getThing();

I would like to extend this returned class and Add/Override a method but leave intacts the others, say 150 methods.

  private class MyWrapperClass extends MyClass(){
      public MyWrapperClass(){super();}
      @Override public String toString(){ return "Blocked toString"; }
  }

Is there any way to force this "casting" from the returned MyClass instance to my newly particular subtype??

NOTE: Please, not suggest the approach of making a constructor, passing the original object and having to copy and implement the 150 methods to call the wrapped object

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
Whimusical
  • 6,401
  • 11
  • 62
  • 105
  • You didn't mention, even though you wrote `MyClass`. Is returned instance a class or an interface? – Less Aug 16 '12 at 09:34
  • 1
    @Less Well since the `MyWrapperClass` extends `MyClass` then it has to be a class. – maba Aug 16 '12 at 09:50

3 Answers3

7

If MyClass is an interface look at java.lang.reflect.Proxy and java.lang.reflect.InvocationHandler.

You can implement a dynamic proxy that always does the same. It is, always pass control to your original implementation... except when method X is invoked.

Something like:

class MyHandler implements InvocationHandler {
  Object invoke(Object proxy, Method method, Object[] args) {
    if (method is the one you want to change) {
       do whatever
    else
       return method.invoke(originalObject, args);
  }
}

Note: you must create this proxy implementation anyway:

MyClass original = ServiceUtil.getThing();
MyClass proxy = (MyClass) Proxy.newProxyInstance(
                                          MyClass.class.getClassLoader(), // classloader to use
                                          new Class[] { MyClass.class }, // interfaces to implement
                                          new MyHandler()); // who does the dirty work when methods are invoked
helios
  • 13,574
  • 2
  • 45
  • 55
  • And... if you like this I should put the proxy creation stuff inside a `MyClass decorate(MyClass)` method, to put all the dirty stuff together. If you tomorrow want to change the way decoration works you only change that method. Your *normal* code doesn't get polluted. – helios Aug 16 '12 at 09:52
  • I think this is the answer I was looking – Whimusical Aug 16 '12 at 12:52
5

I hope I get you right: you have a

MyClass instance = ServiceUtil.getThing();

but want something like

MyWrapperClass instance = (MyWrapperClass) ServiceUtil.getThing();

(which obviously doesn't work, even though MyWrapperClass extends MyClass).

The solution is to create a new instance of MyWrapperClass based on the MyClass and, sorry to say that, using the constructor is a good approach (public MyWrapperClass(MyClass myClass)).

Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
  • Of course it is, but then I would need to rewrite a call to super for the other 150 methods (as proxy methods to underlying object), which is not a nice pattern. – Whimusical Aug 16 '12 at 11:08
  • 1
    A class with 150 methods isn't a nice pattern anyway. So it won't get much worse ;) – Andreas Dolk Aug 16 '12 at 12:02
  • An API returning classes not interfaces (and they're not simple value-objects) is not a nice pattern either. But the API is what it is.... – helios Aug 16 '12 at 12:17
  • Thank you. Everything is a fictional example for understanding best pattern in those situations. I understand when there is only 2 or 3 methods to override that wrapper is nice, but that is why i am asking what to do if there is a loooot of methods and u dont want to miss any – Whimusical Aug 16 '12 at 12:50
1

Please, not suggest the approach of making a constructor, passing the original object and having to copy and implement the 150 methods to call the wrapped object

You mean to say that "decoration" is not an option you would like to look at right?

But decoration will be a problem to you if MyClass is an interface type where you have to define those 150 odd methods, delegating the 149 method calls onto the decorated and overriding that one method.

If MyClass is a class type, then you don't need to write those 149 methods, right? or Did I get you completely wrong?

Vikdor
  • 23,934
  • 10
  • 61
  • 84