Mir
Mir

Reputation: 11

How to find the concrete class of a method parameter

I have the following class structure:

public interface Incoming<P extends Processor> {
   void doSomething(P p);
}

public interface Processor<I extends Incoming> {
      void process(I i);
}

public class MyIncoming implements Incoming<MyProcessor>
{
   public void doSomething(MyProcessor p) { .. }
}

public class MyProcessor implements Processor<MyIncoming> {
 public void process(MyIncoming i) { .. }
}

Now in another class I pass an Instance of MyIncoming that is supposed to initialize the type passed for the Processor it has defined in doSomething()?

Please help.

Upvotes: 0

Views: 169

Answers (1)

Paul Boddington
Paul Boddington

Reputation: 37665

The first problem I see with your code is that you are using the raw types Incoming and Processor.

public interface Incoming<P extends Processor> {
   void doSomething(P p);               ^^
}                               that is a raw type!

One way to get rid of those raw types is to make both Incoming and Processor have two type parameters, but it's very complicated.

public interface Incoming<I extends Incoming<I, P>, P extends Processor<I, P>> {
    void doSomething(P p);
}

public interface Processor<I extends Incoming<I, P>, P extends Processor<I, P>> {
    void process(I i);
}

Now to your actual question. You've said that for each concrete implementation of Incoming you have a specific instance of Processor, and for a variable t of type Incoming, you want to be able to find out that instance x and call x.process(t);. I'm sure that this can be done with reflection, but I can't see the point. You can just make getProcessor a method of Incoming.

public interface Incoming<I extends Incoming<I, P>, P extends Processor<I, P>> {
    void doSomething(P p);
    P getProcessor();
}

Now you can write concrete implementations.

public class MyIncoming implements Incoming<MyIncoming, MyProcessor>
{
    private static final MyProcessor PROCESSOR = new MyProcessor();

    @Override
    public void doSomething(MyProcessor p) { }

    @Override
    public MyProcessor getProcessor() { return PROCESSOR; }
}

public class MyProcessor implements Processor<MyIncoming, MyProcessor> {

    @Override
    public void process(MyIncoming i) { }
}

Now, if you have a generic class

class A<I extends Incoming<I, P>, P extends Processor<I, P>>  

and, within A, you have a variable i of type I, you can do

i.getProcessor().process(i);

This works, but personally I think circular dependencies of the form TypeA<B extends TypeB> / TypeB<A extends TypeA> are unnecessarily convoluted, and the generics here actually work against you. It may preserve your sanity if you just make Incoming and Processor non-generic interfaces and use casting where necessary.

Upvotes: 1

Related Questions