2

假设我有一个返回某个父接口对象的 Java 方法。此函数返回的对象的类没有记录,但是有一个丰富且记录良好的接口层次结构,所有这些都扩展了父接口。例如:

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

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

如果我知道(并且对底层对象的稳定性有信心),我可以编写一个多方法来调度该方法返回的各种对象:

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

但是,由于只有接口是公开的,我宁愿分发这些接口。有没有(好的)方法在接口上进行调度?也许像:

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

2 回答 2

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

请注意,多方法始终isa?在(可能是自定义的)层次结构内部使用。并且(isa? Keyword Callable)是真的。

于 2017-03-07T07:19:34.917 回答
0

您可以使用多方法的调度功能将每个接口映射到一个“调度值”,然后使用这些调度值将事情导向正确的代码。这个调度函数定义了接口之间的隐式层次结构,所以你总是会得到一个代码需要去的地方。

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 的内置层次结构功能以任意方式构建它们。

于 2017-03-06T20:19:56.510 回答