2013-01-24 2 views
7

저는 Scheme 및 Haskell과 같은 기능적 언어에 대해 매우 잘 알고 있습니다. Java에서 문제를 해결하려고 노력 중입니다. 기능적 사고 방식을 사용하고 있기 때문일 수 있습니다.Java Higher Order Polymorphic Function

내가 쓰고 싶은 :와

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

을 적절한 processstoreIn의 유형을 기반으로합니다.

하스켈에서

나는

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 인스턴스를 제공 할 수있다.

이 자바에서 올바른 접근 방식을? 내가 이것을 달성하기 위해 다소 싸우고있는 것처럼 느껴지기 때문에.

+1

방문자 패턴을 사용하면 이중 디스패치로 해결할 수 있다고 생각합니다. – Scorpion

+0

개인적으로, 나는 함수에서 뭔가를 반환하는 것이 더 쉽다. 코드를 읽기 쉽게 만듭니다. Map과 List에 가장 가까운 수퍼 유형을 생각할 수는 없지만 반환 값이 될 것입니다. 그러면 할당 문에서 Map/List로 캐스팅됩니다. 즉, Map myMap = new Map ; myMap = (지도 ) 프로세스 (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 분 늦었습니다 ... –