Reputation: 54094
I have 2 classes e.g. A and B.
These classes have a couple of getter/setter methods with the same name.
Now in the code I do the following:
if(obj.getClassName().equals(A.class.getName())){
A a = (A) obj;
String result = a.getInfo();
}
else if(obj.getClassName().equals(B.class.getName())){
B a = (B) obj;
String result = a.getInfo();
}
I was wondering if there is a way to call the getInfo
avoiding the if statements.
Note: I can not refactor the classes to use inheritence or something else.
I was just interested if there is a trick in java to avoid the if statements.
Upvotes: 1
Views: 1290
Reputation: 11
If obj is declared as either A or B, you can use overloaded methods. (A good argument for type safety.) Here's a test that illustrates this:
import static org.junit.Assert.*;
import org.junit.Test;
public class FooTest {
class A {
public String getInfo() {
return "A";
}
}
class B {
public String getInfo() {
return "B";
}
}
public String doBarFor(A a) {
return a.getInfo();
}
public String doBarFor(B b) {
return b.getInfo();
}
public String doBarFor(Object obj) {
throw new UnsupportedOperationException();
}
@Test
public void shouldDoBarForA() {
A a = new A();
assertEquals("A", doBarFor(a));
}
@Test
public void shouldDoBarForB() {
B b = new B();
assertEquals("B", doBarFor(b));
}
@Test(expected = UnsupportedOperationException.class)
public void shouldFailIfDeclaredAsObject() {
Object a = new A();
assertEquals("A", doBarFor(a)); // exception thrown
}
}
Upvotes: 1
Reputation: 25174
You need reflection. here is my complete example.
Class A
package a;
public class A {
String info;
public String getInfo() {
System.out.println("A getInfo");
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
Class B
package a;
public class B {
String info;
public String getInfo() {
System.out.println("B getInfo");
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
Test Class
package a;
import java.lang.reflect.Method;
public class TestAB {
public static void main(String[] args) {
A a= new A();
doSth(a);
}
private static void doSth(Object obj) {
Class c = obj.getClass();
Method m;
try {
m = c.getMethod("getInfo", new Class[] { });
String result = (String) m.invoke(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
}
See this line :
Class c = obj.getClass();
and
m = c.getMethod("getInfo", new Class[] { });
and
String result = (String) m.invoke(obj);
There is no if
statements
Upvotes: 1
Reputation: 6776
In Java you can use a dot as a scope resolution operator with static methods. Try something like this:
String a_info = A.getInfo();
String b_info = B.getInfo();
With objects, if two interfaces really have the same method with the same parameters and the same return type, why must they be treated differently? Take a look here for some more insight into the problem.
Good luck.
Upvotes: 0
Reputation: 143966
If obj
is an Object, you'll need to check. If you don't want to use an if-statement, you can try just casting and catch the exception:
String result = null;
try {
result = ((A)obj).getInfo();
}
catch(ClassCastException e1) {
try {
result = ((B)obj).getInfo();
}
catch(ClassCastException e2) {
// do something else
}
}
Another thing you can do is make both classes implement an Interface then check for just that Interface, something like:
public interface HasInfo
{
public String getInfo();
}
Then add implements HasInfo
in the class definition for A and B. Then you can just check (or cast) to HasInfo
.
Upvotes: 0
Reputation: 526
Refer to : this tutorial if this is what you were trying to achieve.
Upvotes: 0
Reputation: 258678
If you can't use inheritance and want to avoid if
statements (even using instanceof
)... well... the best you can do is wrap the check, cast and call in a function to avoid code duplication... otherwise there's no way to do this.
Upvotes: 1
Reputation: 1503799
Unless you want to use reflection, no. Java treats two types which happen to declare the same method (getInfo()
) as entirely separate, with entirely separate methods.
If you've got commonality, you should be using a common superclass or a common interface that both of them inherit. You've tagged the question "design-patterns" - the pattern is to use the tools that the language provides to show commonality.
As Eng.Fouad shows, using instanceof
is simpler anyway - and better, as it means your code will still work with subclasses of A
or B
.
You can isolate this ugliness, of course, by putting it in a single place - either with a facade class which can be constructed from either an A
or a B
, or by having a single method which performs this check, and then calling that from multiple places.
Upvotes: 6
Reputation: 117675
How about:
String result = null;
if(obj instanceof A)
{
result = ((A) obj).getInfo();
}
else if(obj instanceof B)
{
result = ((B) obj).getInfo();
}
Upvotes: 0