2017-03-06 3 views
2

부모 인터페이스의 객체를 반환하는 Java 메소드가 있다고 가정 해 보겠습니다. 이 함수가 반환하는 객체의 클래스는 문서화되어 있지 않지만 부모 인터페이스를 모두 확장 한 풍부하고 잘 문서화 된 인터페이스 계층 구조가 있습니다. 그래서 예를 들면 :Java 인터페이스에서 Clojure Multimethod 디스패치

(defmulti place-setting class) 
(defmethod place-setting Omelet [meal] ...) 

: 내가 아는 (및 안정성에 확신) 기본 객체 경우

public class Person { 
    public IMeal favoriteMeal() { ... } 
} 

public interface IBreakfast extends IMeal { ... } 
public interface ILunch extends IMeal { ... } 
public interface IBrunch extends IBreakfast, ILunch { ... } 

는, 그 메소드에 의해 반환되는 다양한 개체에 파견하는 multimethod를 작성할 수 그러나 공용 인터페이스 만 있기 때문에 필자는 해당 인터페이스를 공개 할 것입니다. 인터페이스를 파견하는 좋은 방법이 있습니까? 아마도 같은 :

(defmulti place-setting magic-interface-dispatch-fn) 
(defmethod place-setting IBreakfast [meal] ...) 

답변

4

이 이미 완벽하게 잘 작동 :

참고 : 다음

public interface IFn extends Callable, Runnable 
public class Keyword implements IFn 

그리고 :

(defmulti print-stuff class) 
(defmethod print-stuff Callable [x] {:callable x}) 
(defmethod print-stuff :default [x] :not-found) 
(print-stuff :foo) ;; => :callable 

주, multimethods 항상 내부적으로 (잠재적으로 사용자 정의) 계층에 isa?를 사용합니다. (isa? Keyword Callable)이 참입니다.

+0

Welp, 이제 나는 바보처럼 느껴진다. 'isa? '부분을 설명해 주셔서 감사합니다. 그것이 제가 놓친 부분이었습니다. – user12341234

0

당신은 "파견 값"을 각각의 인터페이스를 매핑 multimethods의 파견 기능을 사용할 수 있습니다 다음 올바른 코드에 물건을 직접 이러한 파견 값을 사용합니다. 이 디스패치 함수는 인터페이스 간의 암시 적 계층 구조를 정의하므로 항상 코드가 정확히 하나만 있어야합니다.

hello.core> (defmulti foo (fn [meal] (condp instance? meal 
             java.util.Collection ::breakfast 
             java.lang.Double ::lunch))) 
nil 
hello.core> (defmethod foo ::breakfast 
       [meal] 
       (count meal)) 
#multifn[foo 0x2b6e7712] 
hello.core> (defmethod foo ::lunch 
       [meal] 
       meal) 
#multifn[foo 0x2b6e7712] 
hello.core> (foo 2.3) 
2.3 
hello.core> (foo [1 2 3]) 
3 

디스패치 기능의 계층 구조를 정의하는 것이 귀찮을 경우

, 당신은 이러한 임의의 방식으로 구축 할 수 clojure's built in hierarchy feature를 사용하여 전환 할 수 있습니다.