7

私は、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 */
    }
}

process最初のメソッドが、指定された型に基づいて適切なメソッドを呼び出すことができるようにしますstoreIn

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

Storeable保存したいコレクションタイプのインスタンスを提供しますResultSet

これはJavaで正しいアプローチですか? これを達成するために言語と戦っているような気がするからです。

4

3 に答える 3

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 */
    }
}
于 2013-01-24T16:54:47.483 に答える
2

いいえ、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 インジェクションの脆弱性が悪いことであることに言及する必要がないことを願っています。(これもJava でMapはありません(C# ではありCollectionますが、C#Collectionはあまり役に立ちません)。)

于 2013-01-24T17:00:34.550 に答える
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 */
    }
}
于 2013-01-24T16:55:52.647 に答える