Search code examples
javainheritanceinstanceofdynamic-caststatic-typing

Use a static type only obtainable at runtime


Let's say I have a situation as follows:

A class X has a field s of type S.

S is extended by two classes A and B both implementing some same methods/fields that we all know should then be implemented in S but, unfortunately, this is not the case.

Now I want to do something like this:

"A or B" downcast_field;
if(s instanceof A)
    downcast_field = (A)s;
else if (s instanceof B)
     downcast_field = (B)s;

//do something common for the two cases but that need methods implemented both in A and B

The problem is then having in advance a static type (out of the IFs) that allows me to call such methods.

I guess that due to bad design this is actually impossible and I have to write twice the same code, which is ugly, but perhaps there is a solution that I am not seeing right now.


Solution

  • If you can change A and B, then you can add the same interface to both. That would allow you to give this type to downcast_field and invoke methods.

    If you can't change A and B, then you have two options:

    • You can write A2 and B2. Copy the code from A and B into the new types. That allows you to modify the code (unless you can't control the creation of those types). Alternatively, you could also now create S2 which extends S and put the common code in there and then extend A2/B2 from that.

    • Create an interface and then two implementations which just delegate the calls to the real type.

      In this solution, you can

      Wrapper downcast_field;
      if(s instanceof A)
          downcast_field = new AWrapper( (A)s );
      else if (s instanceof B)
          downcast_field = new BWrapper( (B)s );
      
      downcast_field.foo();
      

      You can make the two wrappers extend the same type and move common code there.