Clojure gen-class用于重载和覆盖方法

7
我正在尝试使用gen-class在clojure中重写此类中的compare(WriteableComparable a, WriteableComparable b)方法,但麻烦在于该方法被重载了3次:
  • int compare(WritableComparable a, WritableComparable b)
  • int compare(Object a, Object b)
  • int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2)
到目前为止,我的尝试看起来像这样:
(gen-class
 :name comparators.MyWriteableComparator
 :extends org.apache.hadoop.io.WritableComparator
 :exposes-methods {compare superCompare}
 :prefix "interop-")

(defn interop-compare
  ([this a b c d e f]
     (.superCompare this a b c d e f))
  ([this ^WritableComparable w1 ^WritableComparable w2]         
     (.compareTo (.getSymbol ^SymbolPair w1) 
                 (.getSymbol ^SymbolPair w2))))

一切都编译通过了,但是当我运行它时,会得到一个空指针异常。我怀疑这是因为我覆盖了错误的方法(即compare(Object a, Object b)而不是预期的compare(WritableComparable a, WritableComparable b))。供参考compareObject版本会调用WriteableComparable版本。

很有可能NPE来自其他地方,但是我至少将其缩小到这个Clojure代码上(当我使用相应的Java版本运行它时,一切正常)。

有没有办法指定要使用哪个重载的方法?

(我尝试在gen-class调用中添加:methods子句,但我了解到只应声明新方法,而不是超类方法。)

1个回答

9
有一种机制可以与gen-class配合使用,允许覆盖同参数数量的重载方法。我们可以定义变量/函数名称包括参数类型,除了前缀和方法名称。要覆盖像foo(String s, Object o)这样的方法,我们可以定义一个名为-foo-String-Object的变量。代码将寻找这个变量名,如果没有找到,则会回退到-foo。这在至少Clojure邮件列表线程之一中有记录。
实际上,这意味着你可以编写如下的代码:
(defn interop-compare [this a b c d e f]
  (do-array-compare))

(defn interop-compare-Object-Object [this a b]
  (do-object-compare))

(defn interop-compare-WritableComparable-WritableComparable [this a b]
  (do-writable-comparable-thing))

哇,gen-class 的使用方式又多了一种神秘的方法。我曾经想过这个问题,但并不需要答案,所以把它放在了脑后。 - Mars
为了日后参考,请注意添加以下内容:在 interop-compare 方法中,需要增加一个输入为 Object Object 的副本和一个输入为 WritableComparable-WritableComparable 的副本,以使其正常工作。 - Didier A.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接