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