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:
createView()
method into my own class that inherits from the factory classThe 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.
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.
Monkey patching is the first step towards meta-programming - writing code which writes code.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With