errr errr - 11 months ago 51
Java Question

How to dynamically and recursively decorate a class in Java/Scala?

Say I'm modeling dreams:

public interface Dream {

void start();

public class SimpleDream implements Dream {
// implementation here...

public class Inception implements Dream {

Dream inner;

// implementation here...

Now say I have a decorator class for these dreams:

public class Decorator implements Dream {

Dream decorated;

public void start() {

// do something else

I want to be able to write a method that'll take any
instance and decorate it with
recursively (fields as well). I was able to write such a method with reflection, but I encountered a problem when trying to decorate a field of a sub-type of

public class LucidDream implements Dream {

SimpleDream inner;

// implementation here...

My generic method will try to set a new
wrapping the
into the
field of
, and doing so (with
) will throw an exception (
java.lang.IllegalArgumentException: Can not set final X field Y to Z

I tried using proxies but it didn't work.


I'm actually using Scala, so (a) forgive me for my Java code, and (b) if this is somehow achievable only with Scala, I'd like to know that as well.

Answer Source

Unfortunately, you said you can't change LucidDream.inner

class LucidDream implements Dream{
  SimpleDream inner; // CANNOT be changed to "Dream"

In that case, to the best of my knowledge, life becomes more complicated, and the only workaround would be to dynamically extend SimpleDream, using byte code enhancement libraries such as cglib. See discussion here (ignore the fact they're discussing an abstract class - the main point is dynamically extending a class rather than interface):

Alternatives to java.lang.reflect.Proxy for creating proxies of abstract classes (rather than interfaces)

However, this is not trivial (this complicates maintenance as well as code deployment) so I'd resort to it only if I really had no choice, namely I really needed this level of generalization, and I really couldn't change to "Dream inner"....