I have a class called X that implements multiple (e.g. 3) interfaces, call them A, B and C.
I create another interface AB that extends interface A and B.
How can I use reflection to create an instance of X that is assignable to interface AB?
I keep getting ClassCast exceptions with this code:
package test.messages;
public interface A
{
void methodA();
}
package test.messages;
public interface B
{
void methodB();
}
package test.messages;
public interface C
{
void methodC();
}
package test.messages;
public interface AB extends A, B
{
}
package test.messages;
public class X implements A, B, C
{
@Override
public void methodC()
{
System.out.println("C");
}
@Override
public void methodB()
{
System.out.println("B");
}
@Override
public void methodA()
{
System.out.println("A");
}
}
Then in a completely different class:
AB api = (AB)Class.forName("test.messages.X").newInstance();
System.out.println(api);
Now when I try with just one interface, say A, it works fine.
Is there anyway to get it to work with the combined interface AB?
What you really want is AND type -- A&B
. This is generally not supported in Java. However, we could create a wrapper class that contains a value that is both type A and type B. (It seems that every problem can be solved by a wrapper:)
public class AB<T extends A&B>
{
public final T v;
...
v = (T)Class.forName("test.messages.X").newInstance();
}
Instead of using type A&B
, we use AB<?>
everywhere it's needed. We'll operate on its field v
, which is both A
and B
.
void foo(AB<?> ab)
{
ab.v.methodOfA();
ab.v.methodOfB();
}
Or you could make AB
a subtype of A and B too.
public class AB<T extends A&B> implements A, B
{
public final T v;
@Override // A
public int methodOfA(){ return v.methodOfA(); }
See more at https://stackoverflow.com/a/32659085/2158288
The is-a relationship doesn't work that way. The fact that AB
implements A
and B
and X
implements A
and B
doesn't make X
assignable to AB
.
Even if you could think that AB
is compatible with any type that implements A
and B
that's not the case as AB
is a different type and the hierarchy tree in Java is fixed with the definition of the classes themselves.
Think about the Liskov substitution principle: if you add a method to AB
then X
is not a valid candidate anymore since it wouldn't contain the method declared in AB
.
You would need a programming language that supports a structural type system to do it.
You can't do that because in the inheritance tree X does not implement AB.
If A,B,C are all interfaces a easy way to fix the problem is to say that X implements AB,C which that means it can be cast as A, as B, as C and as AB.