Skip to main content
 首页 » 编程设计

servlets之如何定义实现 servlet 接口(interface)的 clojure 类型

2024年07月26日13zhengyun_ustc

我正在尝试使用 deftype(来自前沿的 clojure 1.2 分支)来创建一个实现 java Servlet 接口(interface)的 java 类。我希望下面的代码能够编译(尽管它不是很有用)。

(ns foo [:import [javax.servlet Servlet ServletRequest ServletResponse]]) 
 
(deftype servlet []  
   javax.servlet.Servlet  
   (service [this  
         #^javax.servlet.ServletRequest request 
         #^javax.servlet.ServletResponse response] 
   nil)) 

但是它无法编译。编译器生成消息:

Mismatched return type: service, expected: void, had: java.lang.Object 
  [Thrown class java.lang.IllegalArgumentException] 

这对我来说没有意义,因为我返回零。因此,该方法的返回类型为 void 应该不是问题。例如,对于 java.util.Set 接口(interface):

(deftype bar [#^Number n] java.util.Set (clear [this] nil)) 

编译没有问题。

那么我在 Servlet 接口(interface)上做错了什么?

需要明确的是: 我知道典型的情况是子类化 servlet 抽象类之一,而不是直接实现此接口(interface),但仍然应该可以做到这一点。

堆栈跟踪:

(deftype servlet... 的堆栈跟踪是:

Mismatched return type: service, expected: void, had: java.lang.Object 
  [Thrown class java.lang.IllegalArgumentException] 
 
Restarts: 
 0: [ABORT] Return to SLIME's top level. 
 
Backtrace: 
  0: clojure.lang.Compiler$NewInstanceMethod.parse(Compiler.java:6461) 
  1: clojure.lang.Compiler$NewInstanceExpr.build(Compiler.java:6119) 
  2: clojure.lang.Compiler$NewInstanceExpr$DeftypeParser.parse(Compiler.java:6003) 
  3: clojure.lang.Compiler.analyzeSeq(Compiler.java:5289) 
  4: clojure.lang.Compiler.analyze(Compiler.java:5110) 
  5: clojure.lang.Compiler.analyze(Compiler.java:5071) 
  6: clojure.lang.Compiler.eval(Compiler.java:5347) 
  7: clojure.lang.Compiler.eval(Compiler.java:5334) 
  8: clojure.lang.Compiler.eval(Compiler.java:5311) 
  9: clojure.core$eval__4350.invoke(core.clj:2364) 
 10: swank.commands.basic$eval_region__673.invoke(basic.clj:40) 
 11: swank.commands.basic$eval_region__673.invoke(basic.clj:31) 
 12: swank.commands.basic$eval__686$listener_eval__687.invoke(basic.clj:54) 
 13: clojure.lang.Var.invoke(Var.java:365) 
 14: foo$eval__2285.invoke(NO_SOURCE_FILE) 
 15: clojure.lang.Compiler.eval(Compiler.java:5343) 
 16: clojure.lang.Compiler.eval(Compiler.java:5311) 
 17: clojure.core$eval__4350.invoke(core.clj:2364) 
 18: swank.core$eval_in_emacs_package__320.invoke(core.clj:59) 
 19: swank.core$eval_for_emacs__383.invoke(core.clj:128) 
 20: clojure.lang.Var.invoke(Var.java:373) 
 21: clojure.lang.AFn.applyToHelper(AFn.java:169) 
 22: clojure.lang.Var.applyTo(Var.java:482) 
 23: clojure.core$apply__3776.invoke(core.clj:535) 
 24: swank.core$eval_from_control__322.invoke(core.clj:66) 
 25: swank.core$eval_loop__324.invoke(core.clj:71) 
 26: swank.core$spawn_repl_thread__434$fn__464$fn__465.invoke(core.clj:183) 
 27: clojure.lang.AFn.applyToHelper(AFn.java:159) 
 28: clojure.lang.AFn.applyTo(AFn.java:151) 
 29: clojure.core$apply__3776.invoke(core.clj:535) 
 30: swank.core$spawn_repl_thread__434$fn__464.doInvoke(core.clj:180) 
 31: clojure.lang.RestFn.invoke(RestFn.java:398) 
 32: clojure.lang.AFn.run(AFn.java:24) 
 33: java.lang.Thread.run(Thread.java:637) 

请您参考如下方法:

尝试不使用任何类型提示:

(deftype servlet [] 
  javax.servlet.Servlet 
  (service [this request response] 
    ...body...)) 

来自the web page about deftype :

  • if you leave out all hints: will try to match on same name/arity method in interface(s)

    • this is preferred
    • if you supply any hints at all, no inference is done, so all hints (or default of Object) must be correct, for both arguments and return type

来自(doc deftype):

If not supplied, they will be inferred, so type hints should be reserved for disambiguation.