Reputation: 25285
I'd like to be able to call "getProgram" on objects which have that method, without knowing which class they belong to. I know I should use an interface here, but I'm working with someone else's code and can't redesign the classes I'm working with. I thought BeanUtils.getProperty might help me, but it seems it only returns strings. Is there something like Beanutils.getProperty that will return a cast-able object? Or another, smarter way to work with two similar classes that don't share an interface? thanks, -Morgan
Upvotes: 3
Views: 3383
Reputation: 49331
java.beans.Expression will do that, as long as the method is accessible in the concrete class of the receiver.
public static void main(String[] args) throws Exception {
new Expression(new A(), "doSomething", null).getValue();
new Expression(new B(), "doSomething", null).getValue();
}
public static class A {
public void doSomething() {
System.out.println("I'm doing it already!");
}
}
public static class B {
public void doSomething() {
System.out.println("I'm doing it too!");
}
}
Upvotes: -1
Reputation: 533780
A slightly shorter version if you have Java 5+
public static void main(String[] args) throws Exception {
System.out.println(invoke("toString", new A());
System.out.println(invoke("toString", new B());
}
private static <R> R invoke(Object object, String methodName) throws Exception {
return (R) object.getClass().getMethod(methodName).invoke(object);
}
Upvotes: 0
Reputation: 328760
A pretty simple solution: Use delegation which implements the interface:
interface GetProgram
{
String getProgram ();
}
class AWrapper implements GetProgram
{
A a;
public AWrapper (A a) { this.a = a;
String getProgram () { return a.getProgram(); }
}
Now you can use the interface in your code without touching the original classes.
Drawback: This doesn't work well if you A is created somewhere outside of your reach. It works best if A is created once under your control and you can wrap it immediately.
Upvotes: 0
Reputation: 147154
Presumably you have a finite number of classes implementing this method, and you can link to them directly. So you don't need reflection. Reflection is evil.
Say you have a set of classes with the method:
public class LibA { public Program getProgram() { return program; } ... };
public class LibB { public Program getProgram() { return program; } ... };
...
Then you just need instanceof/cast pairs. You can put this in a method so that you only need to do it once.
public static Program getProgram(Object obj) {
if (obj instanceof LibA) {
return ((LibA)obj).getProgram();
} else if (obj instanceof LibB) {
return ((LibB)obj).getProgram();
} else {
throw new IllegalArgumentException(obj+" doesn't have a known getProgram");
// Or an appropriate application exception.
}
}
Alternatively you might want to use an adapter:
public interface ProgramContainer {
Program getProgram();
...
}
public class LibAContainer implements ProgramContainer {
private final LibA libA;
public LibAContainer(LibA libA) {
this.libA = libA;
}
public Program getProgram() {
return libA.getProgram();
}
...
}
Upvotes: 0
Reputation: 2009
Use PropertyUtils (from apache commons-beanutils) instead of BeanUtils.
It has a getProperty(Object bean, String name) method that returns an Object instead of a String.
See the JavaDoc for more information.
Upvotes: 5
Reputation: 21184
Just use reflection for this... the following example shows how to do it on objects that have no common interface.
public static void main(String[] args) throws Exception {
doSomething(new A());
doSomething(new B());
}
private static void doSomething(Object object) throws Exception {
Method m = object.getClass().getMethod("doSomething", (Class[])null);
m.invoke(object, (Object[])null);
}
private static class A {
public void doSomething() {
System.out.println("I'm doing it already!");
}
}
private static class B {
public void doSomething() {
System.out.println("I'm doing it too!");
}
}
Upvotes: 2
Reputation: 30449
See the Reflection API:
Use Class.getMethod() (or getMethods()) to find the appropriate method and invoke it.
Upvotes: 0