0

Я пытаюсь реализовать интерфейс, представляющий арифметические выражения. Интерфейс будет использоваться java-side, но вся логика находится на clojure.Смешивание definterface и defprotocol

Наличие:

(defprotocol ExtendsExpression 
    (toTree [this])) 

(extend-type String 
    ExtendsExpression 
    (toTree [this] (symbol this))) 

(extend-type Number 
    ExtendsExpression 
    (toTree [this] this)) 

(definterface Expression 
    (toTree [])) 

(defrecord Expression1 [^String oper arg] 
    Expression 
    (toTree [this] 
    (list (symbol oper) (toTree arg)))) 


(defrecord Expression2 [^String oper arg1 arg2] 
    Expression 
    (toTree [this] 
    (list (symbol oper) (toTree arg1) (toTree arg2)))) 

(defrecord Expression3 [^String oper arg1 arg2 arg3] 
    Expression 
    (toTree [this] 
    (list (symbol oper) (toTree arg1) (toTree arg2) (toTree arg3)))) 

Я пытаюсь использовать его как:

(toTree (Expression3. "+" "a" "b" (Expression2. "*" "c" "d"))) 

, но я получаю:

IllegalArgumentException No implementation of method: :toTree of protocol: #'user/ExtendsExpression found for class: user.Expression3 clojure.core/-cache-protocol-fn (core_deftype.clj:541) 

Почему Clojure пытается вызвать toTree из ExtendsExpression для expression3 ? Я ожидаю, что для Expression3 он вызовет метод toTree интерфейса Expression.

ответ

2

Хорошо, Понял;)

(defprotocol ExtendsExpression 
    (to-tree [this])) 

(extend-type String 
    ExtendsExpression 
    (to-tree [this] (symbol this))) 

(extend-type Number 
    ExtendsExpression 
    (to-tree [this] this)) 

(definterface Expression 
    (toTree [])) 

(defrecord Expression1 [^String oper arg] 
    ExtendsExpression 
    (to-tree [this] 
    (list (symbol oper) (to-tree arg))) 
    Expression 
    (toTree [this] (to-tree this))) 


(defrecord Expression2 [^String oper arg1 arg2] 
    ExtendsExpression 
    (to-tree [this] 
    (list (symbol oper) (to-tree arg1) (to-tree arg2))) 
    Expression 
    (toTree [this] (to-tree this))) 

(defrecord Expression3 [^String oper arg1 arg2 arg3] 
    ExtendsExpression 
    (to-tree [this] 
    (list (symbol oper) (to-tree arg1) (to-tree arg2) (to-tree arg3))) 
    Expression 
    (toTree [this] (to-tree this))) 

(to-tree (Expression3. "+" "a" "b" (Expression2. "*" "c" "d"))) ;=> (+ a b (* c d)) 

и записи реализует интерфейс Expression, так что я могу назвать их из Java легко:

(.toTree (Expression3. "+" "a" "b" (Expression2. "*" "c" "d"))) ;=> (+ a b (* c d)) 

просто проверить, какие интерфейсы реализует expression3:

(-> Expression3 clojure.reflect/reflect :bases pprint) 
#{clojure.lang.IHashEq java.io.Serializable clojure.lang.IKeywordLookup 
    clojure.lang.IPersistentMap clojure.lang.IRecord java.lang.Object 
    user.ExtendsExpression clojure.lang.IObj clojure.lang.ILookup 
    user.Expression java.util.Map} 
+0

+1 - решена собственная проблема. –

Смежные вопросы