Java高阶多态函数

我对Scheme,Haskell等功能语言非常熟悉。 我试图解决Java中的一个问题并且挣扎,可能是因为我仍然处于功能性思维模式。

我想写:

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

带有如下界面:

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

和一个实现如下接口的类:

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

以便第一个方法可以根据给定的storeIn类型调用适当的process

在Haskell中,我可以写

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

并为我想存储我的ResultSet任何集合类型提供Storeable实例。

这是Java中的正确方法吗? 因为我觉得我有点为了达到这个目的而与语言作斗争。


不,Java不这样做。

您需要执行以下操作:

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

或者更有可能:

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

我希望我不需要提及SQL注入漏洞是一件坏事。 (另外Map不是Java中的Collection (它在C#中,但C# Collection不是很有用)。)


不幸的是你不能这么做。 编译器必须在编译时知道这个调用绑定了哪个方法。 如果您想根据对象的运行时类型决定调用哪个方法,则必须手动检查它:

你可以做的最多:

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/68907.html

上一篇: Java Higher Order Polymorphic Function

下一篇: Single Sign on with 2 subdomains, one Java, one .NET