I am very familiar with functional langauges such as Scheme, and Haskell. I'm trying to solve a problem in Java and struggling, possibly because I'm still in a functional mindset.
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 implementing the interface like:
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
based on what type of storeIn
it's given.
In Haskell I could write
class Storeable c a where
store :: a -> c a -> c a
doQueryAndStoreData :: Storeable c a => ResultSet a -> c a -> c a
doQueryAndStoreData (ResultSet rs) coll = foldr store coll rs
and provide Storeable
instances for whatever collection type I want to store my ResultSet
in.
Is this the correct approach in Java? Because I feel like I'm somewhat fighting the langauge to accomplish this.
No, Java doesn't do that.
You'd 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 don't need to mention SQL injection vulnerabilities are a bad thing. (Also Map
is not a Collection
in Java (it is in C# but C# Collection
isn't very useful).)
You cannot do that, unfortunately. The compiler must know at compile time which method this call is bound to. If you want to decide which method to call based on the runtime type of the object, you have 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 */
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With