Hello to the community.

Is it possible (and if so, is it worth it) to do without conditional constructions if you need to use different algorithms for different types of input data?

For example, there is a table with data (you can walk through the cells) and there is an array of values ​​of the appropriate dimension, which should be in this table. Each of the values ​​can be of one of several types (suppose, String or Image) and must be checked against the cell in its own way. Is it possible to organize a check so as to avoid (not transfer, but not use at all) constructions like

if (expected instanceof String) {...} 

As I understand it, if it is possible, then with the help of generalizations, but I cannot figure out how.

UPD. Values ​​for checking are stored in variables of the same type - Object, since they are passed through a single structure (for example, like this: Object[] expectedValues ). Therefore, it does not work to rely on type checking when compiling.

    4 answers 4

    Smacks Pattern Strategy. Divide objects by type and assign a strategy for each type.

    For example, something like this

     abstract class MyObject { Types getType(); } interface ProcessingStrategy { void process(MyObject object); } enum Types { IMAGE(MY_IMAGE_STRATEGY), TEXT(MY_TEXT_STRATEGY), CUSTOM(CUSTOM_STRATEGY); private final ProcessingStrategy strategy; private Types(ProcessingStrategy strategy) { this.strategy = strategy; } public ProcessingStrategy getStrategy() { return strategy; } } //...... List<MyObject> objs = .... for (MyObject obj : objs) obj.getType().getStrategy().process(obj); 

    PS: what do you think Generics use for this? I can not imagine this. Generics only work at compile time + check in runtime. So what you want will be impossible

    • Initially I wanted to avoid wrapping existing data types with my own, but apparently, this is inevitable. Thank you, let's see if it will be worth it, then I will use the strategy. - yozh
    • one
      You can also make classes on strategy maps. Then you don’t have to make wrapper classes, but you’ll have to support the map. - cy6erGn0m

    easy way:

     interface TypeHandler { public void handle ( Object object ); public boolean canHandle(Object object); } class GenericHandler implements TypeHandler { private final List < TypeHandler > handlers = new LinkedList < TypeHandler > (); public GenericHandler () { // инициализируем список в правильном порядке } @Override public boolean canHandle ( final Object object ) { return true; } @Override public void handle ( final Object object ) { for ( final TypeHandler handler : handlers ) { if ( handler.canHandle ( object ) ) { handler.handle ( object ); } } } } 

      more advanced:

       interface TypeHandler { public void handle ( Object object ); } class DefaultHandler implements TypeHandler { @Override public void handle ( final Object object ) { System.out.println ( object ); } } class NumberHandler implements TypeHandler { @Override public void handle ( final Object object ) { System.out.println ( "number = " + object ); } } class GenericHandler implements TypeHandler { private final Map < Class < ? >, TypeHandler > handlers = new HashMap < Class < ? >, TypeHandler > (); public GenericHandler () { register ( Object.class, new DefaultHandler () ); register ( String.class, new DefaultHandler () ); register ( Number.class, new NumberHandler () ); } public TypeHandler getHandler ( final Object o ) { // default if ( null == o ) { return handlers.get ( Object.class ); } return getHandler ( o.getClass () ); } @Override public void handle ( final Object object ) { getHandler ( object ).handle ( object ); } public void register ( final Class clazz, final TypeHandler typeHandler ) { handlers.put ( clazz, typeHandler ); } public void unregister ( final Class clazz ) { handlers.remove ( clazz ); } private TypeHandler getHandler ( final Class clazz ) { final TypeHandler typeHandler = handlers.get ( clazz ); // handler found if ( null != typeHandler ) { return typeHandler; } // search dynamically for super class handlers return getHandler ( clazz.getSuperclass () ); } } 

      using:

        final GenericHandler hander = new GenericHandler (); hander.handle ( "hello world" ); hander.handle ( new Integer ( 15 ) ); hander.handle ( new Double ( 16.5 ) ); hander.handle ( new Date () ); hander.handle ( new GenericHandler () ); 

      conclusion:

       hello world number = 15 number = 16.5 Thu May 19 21:06:04 EEST 2011 jmu.diplom.steganography.dcp.koh.GenericHandler@1ff9dc36 

        Something like this?

         public boolean check( Image value){ ... } public boolean check( String value ){ ... } public boolean check( int value ){ ... } .... String s = "bla"; if( check( s ) ){ ... } // вызовется public boolean check( String value ){ ... } 
        • thanks, not really that. Updated the question. - yozh
        • The minimum example is to make, that there is such a code, how to do it without an instanceof - Alex Kapustin