Polymorphic function of a higher order

I am very familiar with functional langauges such as Scheme and Haskell. I am trying to solve a problem in Java and struggle, perhaps because I am still in functional thinking.

I want to write:

public void doQueryAndStoreData(String query, <? extends Collection> storeIn) { /* make a jdbc query, get ResultSet */ ResultSet rset = ...; ProcessResultSet proc = new ProcessResultSet(); proc.process(rset, storeIn); /* clean up */ } 

with an interface like:

 private interface IProcessResultSet<C> { public void process(ResultSet rset, C storeIn); } 

and a class that implements the interface, for example:

 private class ProcessResultSet implements IProcessResultSet<? extends Collection> { public void process(ResultSet rset, Map storeIn) { /* do something */ } public void process(ResultSet rset, List storeIn) { /* do something else */ } } 

so that the first method can call the appropriate process depending on what type of storeIn it gave.

In Haskell, I could write

 class Storeable ca where store :: a -> ca -> ca doQueryAndStoreData :: Storeable ca => ResultSet a -> ca -> ca doQueryAndStoreData (ResultSet rs) coll = foldr store coll rs 

and provide Storeable instances for any type of collection in which I want to save my ResultSet .

Is this the right approach in Java? Because I feel that I am somewhat struggling with langauge to accomplish this.

+7
source share
3 answers

No, Java does not.

You will need to do something like:

 public <T> void doQueryAndStoreData( String query, T storeIn, ResultSetProcessor<T> processor ) { 

Or much more likely:

 public void doQueryAndStoreData( String query, ResultSetHandler handler // may contain processor and storeIn ) { 

I hope I do not need to mention that SQL injection vulnerabilities are bad. (Also Map not a Collection in Java (it is in C #, but the C # Collection not very useful).

+2
source

You cannot do this, unfortunately. The compiler must know at compile time to which method this call is bound. If you want to decide which method to call based on the runtime type of the object, you need to manually check it:

The most you can do:

 private class ProcessResultSet implements IProcessResultSet<? extends Collection> { @Override public void process(ResultSet rset, Collection storeIn) { if (storeIn instanceof Set) { return processSet(rset, (Set) storeIn); } else if (storeIn instanceof List) { return processList(rset, (List) storeIn); } else { throw new IllegalArgumentException("Unimplemented storage type"); } } public void processSet(ResultSet rset, Set storeIn) { /* do something */ } public void processList(ResultSet rset, List storeIn) { /* do something else */ } } 
+2
source
 private class ProcessResultSet implements IProcessResultSet<? extends Collection> { public void process(ResultSet rset, Object storeIn) { if ( storeIn instanceof Map) processMap(rset,(Map) storeIn); else if (storeIn instanceof List) processList(rset,(List) storeIn); else System.out.println("Unsupported input type."); } public void processMap(ResultSet rset, Map storeIn) { /* do something */ } public void processList(ResultSet rset, List storeIn) { /* do something else */ } } 
0
source

All Articles