2

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?

3
  • 3
    It looks like you're trying to get an instance of AB from a class that doesn't implement AB. Commented Jan 11, 2016 at 19:43
  • You couldn't, though you could perhaps use a JDK proxy. Commented Jan 11, 2016 at 19:44
  • stackoverflow.com/a/32659085/2158288 Commented Jan 11, 2016 at 19:49

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

You did an excellent job of explaining why my approach didn't work when you mentioned what happens if you add a method to interface AB. However, bayou.io better understood what I was trying to do and how to get there.
1

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

Comments

1

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.

4 Comments

While this would work the real life scenario I am dealing with involves 10 interfaces. So if I were to create a separate interface for every possible combination of those 10 I would have 1061 additional interfaces :)
That is inconvenient, to say the least. The answer is quite interesting although I must admit I don't fully understand how it helps. Don't you still need to create a whole bunch of interface combination wrappers?
I am the service provider exposing a single interface for each service function. I am creating a user document for service consumers who might want to use more than one service at a time. I merely want to show how to combine more than one interface in a single class for the consumer. So I will not be creating combinations but consumers might...
Ok, now it makes sense :) @BigMac66 thanks for the explanation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.