Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to monkey patch in Java?

Tags:

I don't want to discuss the merits of this approach, just if it is possible. I believe the answer to be "no". But maybe someone will surprise me!

Imagine you have a core widget class. It has a method calculateHeight(), that returns a height. The height is too big - this result in buttons (say) that are too big. You can extend DefaultWidget to create your own NiceWidget, and implement your own calculateHeight() to return a nicer size.

Now a library class WindowDisplayFactory, instantiates DefaultWidget in a fairly complex method. You would like it to use your NiceWidget. The factory class's method looks something like this:

public IWidget createView(Component parent) {     DefaultWidget widget = new DefaultWidget(CONSTS.BLUE, CONSTS.SIZE_STUPIDLY);      // bunch of ifs ...     SomeOtherWidget bla = new SomeOtherWidget(widget);     SomeResultWidget result = new SomeResultWidget(parent);     SomeListener listener = new SomeListener(parent, widget, flags);      // more widget creation and voodoo here      return result; } 

That's the deal. The result has the DefaultWidget deep within a hierarchy of other objects. The question - how to get this factory method to use my own NiceWidget? Or at least get my own calculateHeight() in there. Ideally, I'd like to be able to monkey patch the DefaultWidget so that its calculateHeight did the right thing...

public class MyWindowDisplayFactory {     public IWidget createView(Component parent) {         DefaultWidget.class.setMethod("calculateHeight", myCalculateHeight);         return super.createView(parent);     } } 

Which is what I could do in Python, Ruby, etc. I've invented the name setMethod() though. The other options open to me are:

  • Copying and pasting the code of the createView() method into my own class that inherits from the factory class
  • Living with widgets that are too big

The factory class can't be changed - it is part of a core platform API. I tried reflection on the returned result to get to the widget that (eventually) got added, but it is several widget-layers down and somewhere it gets used to initialize other stuff, causing odd side effects.

Any ideas? My solution so far is the copy-paste job, but that's a cop out that requires tracking the changes in the parent factory class when upgrading to newer versions of the platform, and I'd be interested to hear other options.

like image 264
richq Avatar asked Dec 19 '08 15:12

richq


People also ask

What is monkey patching in Java?

Monkey Patching consists of “dynamic modifications of a class or module at runtime, motivated by the intent to patch existing third-party code as a workaround to a bug or feature which does not act as desired,” hence, a monkey patch would not change the software itself, but only the local copy while it's being run.

Is monkey patching metaprogramming?

Monkey patching is the first step towards meta-programming - writing code which writes code.

What is Patch in Ruby?

In Ruby, a Monkey Patch (MP) is referred to as a dynamic modification to a class and by a dynamic modification to a class means to add new or overwrite existing methods at runtime. This ability is provided by ruby to give more flexibility to the coders.


1 Answers

Perhaps you could use Aspect Oriented Programming to trap calls to that function and return your own version instead?

Spring offers some AOP functionality but there are other libraries that do it as well.

like image 156
Andy Avatar answered Sep 19 '22 19:09

Andy