Fabien Henon
Fabien Henon

Reputation: 823

Make a class extends another class at runtime

There is a library have a base class (let's call it CBase) that performs some tasks and one can create classes that extends this CBase class.

The behavior of the CBase is not enough for me, so I would like to create my own CBase class (let's call it MyCBase) that have the same methods and members but these methods don't do the same thing.

Until now everything is ok. But what blocks me is that I would like to replace CBase by MyCBase. However, I have a lot of classes that extend CBase and I don't want to change them all.

Is it possible to replace CBase by MyCBase at runtime ? So that

public class A extends CBase {}

becomes

public class A extends MyCBase {}

Can I perform this using code enhancement ? (like we do to add methods to a class at runtime. Is it also possible to change inheritance this way ?)

Thank you for your help !

EDIT

I would like to write a plugin for a framework, this is why I would like to change inheritance at runtime. This way users of the framework can use my plugin without changing their source code (changing the inheritance of their classes from CBase to MyCBase)

EDIT 2

Is it possible to do like this: ?

CtClass cc = CtClass.forName("pkg.AClass");
cc.setSuperclass(CtClass.forName("mylib.MyCBase"));
cc.compile();

Upvotes: 2

Views: 1991

Answers (3)

meriton
meriton

Reputation: 70584

Changing all derived classes is a simple matter, provided you control their source code:

  1. Create a new class in your project. Call it CBase, and put it in the same package as the library class.
  2. Use the rename/move refactoring of your IDE to rename CBase to MyBase. This will have the IDE rename all references to the renamed/moved class ...
  3. Write the code for MyBase, extending from CBase.

If you can not do this (for instance because some derived classes are in a library you do not control), you replace the implementation of CBase with your own. Simply create a class of the same package and name in your project (the classloader searches the classpath in order, and uses the first class of the proper package and name it finds). This approach however is very brittle, as the compiler can not check binary compability between the old and new version of CBase. The JVM will check this compatibility when classes are loaded, but since classes are only loaded when needed, its hard to test your changes. (Which is why I do not recommend this approach if there are other options).

You could also change the classes as they are loaded my manipulating the class file, that that's going to be even more brittle, and the compiler would allow you to use any additional features MyBase might have. ==> Definitely not a good idea.

Upvotes: 0

Christian Lendel
Christian Lendel

Reputation: 420

I dont think you can change the extends of a class at runtime. I would suggest to change the extends of the objects or build an interface, which contains all the things your need

Upvotes: 0

Eugen Martynov
Eugen Martynov

Reputation: 20140

I'm not expert. Probably you could extend ClassLoader. But I highly recommend don't do it. The replacement will touch many of your classes but it will be clear in code reading and app execution.

I think there is also room for architecture improvement since you have so many classes extend CBase. People are trying to remove dependencies from other libraries or keep it really small. Because in this case you could easily switch to another library or add your own functionality.

Upvotes: 1

Related Questions