Dynamic casting in Java

I have two hierarchies of parallel classes, and I would like to convert objects from one to another. I can do this by manually specifying which transformation to do, but I need to specify the transformation twice: first, when the actual conversion occurs, and second, when I need to call it. Is there a way to specify it only once?

So here is an example that works, but I would like to simplify. There are two conversion functions that let me go between the input classes (bI, cI) and the output classes (bO, cO). It's unavoidable. The instance of comparisons bothers me. Is there an elegant solution to avoid them?

public class ConversionTest {
    static public class aI {}
    static public class bI extends aI {}
    static public class cI extends aI {}

    static public class aO {}
    static public class bO extends aO {}
    static public class cO extends aO {}

    // Convert from bI to bO.
    private static aO convert(bI iVar) {return new bO();}
    // Convert from cI to cO.
    private static aO convert(cI iVar) {return new cO();}

    public static void main(String argv []) {
        // Input variable.
        final aI iVar = new bI();
        // Output variable.
        final aO temp;
        // Perform conversion.
        if(iVar instanceof bI) {
            temp = convert((bI)iVar);
        } else if (iVar instanceof cI) {
            temp = convert((cI)iVar);
        }
    }
}

I would like to do something like this:

final a0 temp = convert(iVar.getClass().cast(iVar));

, . , , ?

final a0 temp = convertHelp({bI,cI}, iVar);

, convertHelp. . ?

.

+3
6

, /, :

class Converter { 
   public ao convert(ai iObj) {
      final Method m = getClass().getDeclaredMethod("cvrt", iObj.getClass());
      return (ao)m.invoke(this, iObj); 
   }

   public ao cvrt(ai iObj) {
      return new ao();
   }

   public bo cvrt(bi iObj) {
      return new bo();
   }

   public co cvrt(ci iObj) {
      return new co();
   }
}
+1

? , , .

class ai
{
    public ao convert()
    {
        return new ao();
    }
}

class bi extends ai
{
    @Override
    public ao convert()
    {
        return new bo();
    }
}

class ci extends ai
{
    @Override
    public ao convert()
    {
        return new co();
    }
}

public static void main(String argv []) {      
// Input variable.      
final aI iVar = new bI();      
// Output variable.      
final aO temp = iVar.convert();
}
+3

, , , , API .

ConvertHelp; Class. , , ConvertHelp .

, , . Java - .

+1
private static aO convert(aI iVar) {
  if (iVar instanceof bI)
    return new bO();
  if (iVar instanceof cI)
    return new cO();
  return new aO();
}
0

, , :

interface IFactory<T> {
   public T createA();
   public T createB();
   public T createC();
}

class ai
{
    public T convert(IFactory<T> f)
    {
        return f.createA();
    }
}

class bi extends ai
{
   @Override
   public T convert(IFactory<T> f)
   {
       return f.createB();
   }
}

class ci extends ai
{
   @Override
   public T convert(IFactory<T> f)
   {
       return f.createB();
   }
}

class FactoryO extends IFactory<ao> {
   public ao createA() {
      return new ao();
   }

   public bo createB() {
      return new bo();
   }

   public co createC() {
      return new co();
   }
}

:

FactoryO f = new FactoryO();
ai ivar = // ...
ao ovar = ivar.convert(f);
0

, , , . , .

ConverterVisitor :

static public interface ConverterVisitor {
  public aO convert(aI iVar);
}

static public class bIConverter implements ConverterVisitor{
  public aO convert(aI iVar){
  // requires a cast from aI to bI
    return new bO();
  }
}

static public class cIConverter implements ConverterVisitor{
  public aO convert(aI iVar){
    // requires a cast from aI to cI
    return new cO();
  }
}

bI cI , , .

, , , - ReflectionVisitor.

, , - . "" . , factory :

static public class ConverterFactory {

public aO convert(aI ai) throws Exception {
  return (aO) ((ConverterVisitor) Class.forName(ai.getClass().getName() + "Converter").newInstance()).convert(ai);
  }
}

Very ugly! but it works!

The second option is to use some kind of registry in your factory. Here is the complete list. This is better because it uses generic tools to avoid multiple clicks.

import java.util.HashMap;
import java.util.Map;

public class Trial {
        static public class aI {}
        static public class bI extends aI {}
        static public class cI extends aI {}

        static public class aO {}
        static public class bO extends aO {}
        static public class cO extends aO {}

        static public interface ConverterVisitor<T extends aI> {
            public aO convert(T iVar);
        }

        static public class bIConverter implements ConverterVisitor<bI>{

          public bIConverter(ConverterFactory converterFactory){
              converterFactory.register(bI.class, this);
          }

          public aO convert(bI iVar){
              return new bO();
          }
        }

        static public class cIConverter implements ConverterVisitor<cI>{

              public cIConverter(ConverterFactory converterFactory){
                  converterFactory.register(cI.class, this);
              }


             public aO convert(cI iVar){
                  return new cO();
             }
         }


        static public class ConverterFactory {
            public Map<Class<?>,ConverterVisitor<?>>converterRegistry = new HashMap<Class<?>, ConverterVisitor<?>>();

            public <T extends aI> void register(Class<T> clazz,ConverterVisitor<T> converter){
                converterRegistry.put(clazz,converter);
            }

            @SuppressWarnings("unchecked")
            public<T extends aI> aO convert(T ai) {
                return ((ConverterVisitor<T>)converterRegistry.get(ai.getClass())).convert(ai);
            }
        }


        public static void main(String argv []) throws Exception {
            // Input variable.
            final aI iVar = new bI();
            // Output variable.
            aO temp = null;
            // the three lines below must be done in some generic place within the program. 
            ConverterFactory factory = new ConverterFactory();
            new bIConverter(factory);
            new cIConverter(factory);

            temp = factory.convert(iVar);
            System.out.println(temp);
        }
}
0
source

Source: https://habr.com/ru/post/1758082/


All Articles