Reputation: 5435
This is exceedingly bad OO, but I am not trying to put this in any kind of code that will be used by anyone but the coders themselves -- it can never be called except for testing by coders.
Here is the problem I am facing: I have a series of classes that are defined externally. I cannot modify them in any way (except of course I could subclass or call them). They have a variety of names but they do not extend any superclasses (except Object), or implement any interfaces. However what I know about each of them is that they have a method called 'call'.
For testing, I am trying to write code that will call any one of these classes' call methods. But, of course, I cannot just say Object.call() because call is not defined for every Object.
Essentially, this will work:
MyClassOne classOne = new MyClassOne();
MyClassOneInput classOneInput = new MyclassOneInput();
classOne.call(classOneInput);
But this will not:
Object clazz = getClassFromElsewhere();
Object clazzInput = getClassInputFromElsewhere();
clazz.call(clazzInput).
Obviously, since Java is a strongly typed language.
BUT, for the sake of 10x faster testing for every person working on this system, can I get around that somehow and somehow use the 'call' method for any Class and any ClassInput? I have no problem if it generates an exception or breaks entirely if the wrong classes are passed.
Please help me violate Object Orientation.
Upvotes: 2
Views: 149
Reputation: 45725
Use Reflection
getClass()
getMethod()
e.g.
java.lang.reflect.Method method;
try {
method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
} catch (SecurityException e) {
// ...
} catch (NoSuchMethodException e) {
// ...
}
Then
try {
method.invoke(obj, arg1, arg2,...);
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
see How do I invoke a Java method when given the method name as a string?
I would also consider looking into Dynamic JVM languages (JRuby, Jython, Groovy) in which doing something like this may look less "Bad OO" and feel more natural
Upvotes: 3
Reputation: 12443
You can use reflection to do this. Check out the reflection API
Here is a simple example:
MyClassOne classOne = new MyClassOne();
MyClassOneInput classOneInput = new MyClassOneInput();
Method m = classOne.getClass().getMethod("call", MyClassOneInput.class);
m.invoke(classOne, classOneInput);
Note: you can use getDeclaredMethod
to get any method, including private and protected ones but you'll need to call "m.setAccessible(true)" on them if they are private/protected.
Upvotes: 8
Reputation: 35598
This is a perfect use for Java Reflection. This is a pseudo-code example, but it would look something like this
Object obj = getExternalObject();
Method meth = obj.getClass().getDeclaredMethod("call");
meth.invoke(obj);
Upvotes: 6