2

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.

Jeremy
  • 21,351
  • 4
  • 61
  • 77
Jeremy
  • 5,061
  • 13
  • 42
  • 76
  • 9
    Do you know about [reflection](http://docs.oracle.com/javase/tutorial/reflect/index.html)? – Ismail Badawi May 16 '12 at 21:31
  • It sounds like you're looking for a feature similar to the [dynamic](http://msdn.microsoft.com/en-us/library/dd264736.aspx) keyword in C# 4 and later. No such thing exists for Java. – Adam Mihalcin May 16 '12 at 21:32
  • You can use reflection to get the list of methods defined by a class. Search the list for 'call()' and invoke it if you find it. I don't know if this is a great idea, but I've done worse. – Tony Ennis May 16 '12 at 21:33
  • Java has reflection for exactly this purpose and it's widely used in tests and Web-related development where you more or less call methods via names only known in String forms. – billc.cn May 16 '12 at 21:34
  • Related question: http://stackoverflow.com/questions/160970/how-do-i-invoke-a-java-method-when-given-the-method-name-as-a-string – Eran Medan May 16 '12 at 21:38
  • I'll let others comment if it's bad OO or not (probably it is) but I don't think it's bad programming, see JavaScript, Ruby, Python... – Eran Medan May 16 '12 at 21:40

3 Answers3

8

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.

Matt Crinklaw-Vogt
  • 10,580
  • 5
  • 39
  • 44
6

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);
Chris Thompson
  • 33,380
  • 11
  • 76
  • 105
3

Use Reflection

  1. get the class using getClass()
  2. find the "call" method using getMethod()
  3. invoke it on the object if found

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

Community
  • 1
  • 1
Eran Medan
  • 41,875
  • 56
  • 175
  • 268