Clojure 什么';这是扩展协议上第二个参数的用法
Clojure 什么';这是扩展协议上第二个参数的用法,clojure,Clojure,扩展协议上的第三个参数有什么用途?如果我有 (defprotocol my-protocol (foo [x])) (extend-protocol my-protocol java.lang.String ; this (foo [x] (.length x))) (foo "fooooo") ; 6 转化为: (defprotocol my-protocol (foo [x])) (extend-protocol my-protocol java.lang
扩展协议
上的第三个参数有什么用途?如果我有
(defprotocol my-protocol
(foo [x]))
(extend-protocol my-protocol
java.lang.String ; this
(foo [x] (.length x)))
(foo "fooooo") ; 6
转化为:
(defprotocol my-protocol
(foo [x]))
(extend-protocol my-protocol
java.lang.Long ; this
(foo [x] (.length x)))
(foo "fooooo") ; it gave an output 6, while I expect it will throws, since I'm extending from Long, where it doesn't have length()
; In the end, it will just check on the args ? (in this case it's x)
在那里我给了它
java.lang.String
,如果我把它改成java.lang.Long
,调用foo
不会抛出任何异常,而Long
上没有length()
。它抛出的唯一情况是foo
is的参数没有length()
如果将String
更改为Long
,则调用foo
时会出现异常,并使用Long:
;; calling foo with a Long:
user=> (foo 1)
IllegalArgumentException No matching field found: length for class java.lang.Long clojure.lang.Reflector.getInstanceField (Reflector.java:271)
如果不将协议扩展到String
,则无法对字符串调用foo
:
;; calling foo with a String with no implementation provided:
user=> (foo "asdf")
IllegalArgumentException No implementation of method: :foo of protocol: #'user/my-protocol found for class: java.lang.String clojure.core/-cache-protocol-fn (core_deftype.clj:537)
当然,如果您先将my protocol
扩展到String
,然后以单独的extend protocol
形式将其再次扩展到Long
,那么foo
可以很好地处理字符串
Clojure不尝试静态地确定
(.length x)
在您扩展协议的类型下是否有意义。我想在这个例子中可能是这样,因为String
是一个最终类,但在一般情况下(非最终类/接口)——或者至少在不改变其动态语义的情况下不是这样。我想OP想知道为什么x
上似乎没有隐式类型标记,也就是说,尽管Long
没有方法length
,但为什么在编译时没有抛出异常。有什么想法吗?(哈,你在我打字的时候回答了。那就别管了。;):-x
实际上是隐式地暗示了这里的类型(协议扩展到的类型),但是类型暗示只是用来避免反射。所以这只是为了抽象,对吗?我不太明白。如果您要求对扩展协议
的类型参数进行最终澄清,他们会告诉Clojure要将协议扩展到哪种类型。静态地确定给定实现对哪些类型有意义是不可能的(如果只是因为可以随时动态创建新类型的话),即使有可能,程序员也可能不希望进行所有这些扩展。@MichałMarczyk我更新了我的问题,只是为了确保你明白我的意思。请看一看。正如我在回答中提到的,如果您将协议扩展到String
,然后扩展到Long
,那么String
的实现不会消失。这就是为什么foo
仍然可以处理字符串。但是现在您还有一个Long
的实现,这是没有意义的,因此如果您使用Long调用foo
,而不是告诉您没有匹配的实现,Clojure将尝试使用您提供的实现,并在执行时遇到问题。