Java Higher Order Polymorphic Function

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 */
    }
}

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 */
    }
}
链接地址: http://www.djcxy.com/p/68908.html

上一篇: 有没有办法在各种平台上本地化应用程序?

下一篇: Java高阶多态函数