2013-01-24 173 views
7

我对功能语言非常熟悉,例如Scheme和Haskell。我试图解决Java中的一个问题并且挣扎,可能是因为我仍然处于功能性思维模式。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正确的做法?因为我觉得我有点为了达到这个目的而与语言作斗争。

+1

我认为你需要什么可以使用访问者模式来解决 - 双调度。 – Scorpion

+0

个人而言,我更倾向于从函数中返回某些东西。倾向于使代码更具可读性。无法想象与Map和List最接近的超类型,但这将是返回值,然后在赋值语句中将其转换为Map/List,即“Map myMap = new Map ; myMap =(地图)process(rset,myMap);“ – anthropomo

回答

2

没有,爪哇不这样做。

你需要做这样的事情:

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不是非常有用)。)

2

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

最你可以做:

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

我迟了1分钟... –