I am working on a project where there are a lot of objects that are created by a library, and I have no access to the creation process of these objects.
The following snippets serve as a good example to illustrate my problem.
Code:
public class Clazz {
//The contents of Clazz are irrelevant
//Clazz is NOT my class. I have no access to its internal structure.
//However, I do have access to Clazz objects that were created elsewhere.
}
ExampleInterface
is an interface that Clazz may or may not implement at compile time.
Code:
public interface ExampleInterface {
public void run();
}
The following code is the problem that I am running into. Take note of the following:
run()
is only called when c is an instance ofExampleInterface
.getRunConditions(Clazz c)
andexecuteClazz(Clazz c)
are both private methods in a class that I do not have access to.- At compile time,
Clazz
will not contain a method namedrun()
. - ExampleExecutor is not my class. I have no access to it in any way (I can't even get an instance of the class).
Code:
public class ExampleExecutor {
public void executeClazz(Clazz c) {
if ((c instanceof ExampleInterface) && getRunConditions(c)) {
ExampleInterface ex = (ExampleInterface) c;
ex.run();
}
}
}
Obviously the following method isn't syntactically possible, but it is what I am trying to achieve. Basically, if c doesn't already implement ExampleInterface
, set c to implement ExampleInterface
, and then provide the methods that must be overridden.
Take note of the following:
extendInterface(
Name of Interface
)
is made-up syntax I created in an attempt to illustrate my goal.run()
must be defined here (at runtime).- I cannot use a wrapper or proxy class as a solution. IE, the
Clazz
object must wind up implementingExampleInterface
, and I can't use a workaround. (refer to this link if you want to know why).
Code:
public void implementInterface(Clazz c) {
if (!(c instanceof ExampleInterface)) {
c.extendInterface(ExampleInterface {
@Override
public void run() {
//code
}
});
}
}
To clarify, the issue that I am running into is that I need to always know when run()
is called in Clazz
. If Clazz
ever doesn't implement ExampleInterface
, I can't know when run()
should be called.
At the same time, I would also like to occasionally add support for run()
when it by default isn't supported. Because I have no access to the creation of Clazz
objects, I can't do this by implementing the interface myself.
Question: Put simply, is it possible to implement an interface (and provide the required methods) at runtime?
NOTE: While the only solution may require reflection (and if so please post it below), the library I am using has a security manager that blocks the use of all reflection. IE, a reflective solution may be of use to others in the future, but will be of no use to me.
Also, I don't mean just using a library in my own program. An already running host application (which is what the library I am using was made for) complies and then runs code that I write for it. If that application doesn't like any of the code that I provide (IE, conflicts with its security manager), the code is never even compiled.
Why I need to do this:
It has to do with the library that I am using. Because ExampleExecutor
is a method that I don't have access to, and I can't control the creation of Clazz, I can't determine when run()
is executed.
The reason why I need to know when run()
is executed is because in actuality, run()
is an event handler that is part of the library I am using.
For example: mouseClicked(CustomMouseEvent evt)
might be a method that is part of the interface CustomMouseListener
. Sometimes the instance of Clazz
I am working with cares when the mouse is clicked (and therefore inherits CustomMouseListener
), while other times it doesn't.
Unlike the Clazz
instance, I always care if the mouse is clicked, and always need the event to be triggered.
In reality, the ExampleInterface
would actually be the following:
public interface CustomMouseListener {
public void mouseClicked(CustomMouseEvent evt);
public void mousePressed(CustomMouseEvent evt);
public void mouseReleased(CustomMouseEvent evt);
//etc
}