Scala或Jython中多方法的替代方法

时间:2009-08-24 19:49:57

标签: scala jython

我经常遇到想要为我无法控制的类添加其他方法的问题。例如,我可能想要一个函数prettyPrint,它可以在没有统一api的不同对象类型上运行(例如特殊的__str__方法)。

Nice语言和R使用multimethods完成此操作,这样可以很好地避免访问者模式。例如,R具有plot()功能。各个程序员可以创建新类来定义数据类型(例如,网络图或股票报价数据)。然后,辅助用户/程序员可以编写绘图功能来填写功能,即使他们无法访问图表或股票代码或其他绘图函数的代码。

鉴于我想稍后添加许多功能,使用class.method()似乎是不可行的。每种类型的许多class_plot()函数似乎也是一个坏主意。定义一个检查类型的大plot()函数是不可扩展的。

什么是多方法的替代方案?特别是,我对可能在Jython和Scala中工作的设计很感兴趣。

4 个答案:

答案 0 :(得分:7)

在Scala中向类添加方法的最简单方法:

implicit def defSum(l: List[Double]): Double = new AnyRef { def sum = l.foldLeft(0.0)(_ + _) }

或者,在Scala 2.8上,处理数字的方法的具体情况

implicit def defSum[T](l: List[T])(implicit n: Numeric[T]) = new AnyRef {
  import n.mkNumericOps
  def sum = l.foldLeft(n.zero)(_ + _)
}

Scala 2.8上不需要这样做,因为它已经定义了sum

您还可以在实例化时添加特征:

// Immutable class
case class Point(x: Int, y: Int)

// Somewhere else in the code    
trait MyPlot {
  self: Point =>
  import self._

  def plot = println("At "+x+", "+y)
}

// Usage
val p = new Point(1,2) with MyPlot
p.plot

无法做的是在对象中动态添加方法(即,在运行时而不是编译时)。在第一种情况下,您说“将此方法添加到此类”。在第二种情况下,您说“使用此特征创建此对象”。这些都没问题,但“将此方法添加到此对象”不是。

答案 1 :(得分:1)

Python和Jython允许使用mixin类,因此您可以使用它们来保存“扩展”方法:

class Derived(Base, Mixin1, Mixin2, ...):
    ...

显然,如果你想要不同类型的大量plot方法,那么你需要在某处实现 - 这可能会导致多个mixin类。另一种方法是使用字典,其中键是类型,值是函数(或函数集):请参阅this answer

我还假设您不想使用猴子补丁类,这在技术上也是可行的(虽然不可取)。

答案 2 :(得分:1)

Scala具有Implicits的概念。这是an analogy to C#'s extension methods

答案 3 :(得分:1)

如果你不想implement multimethods yourself,那么Python就有packaged implementation of multimethods。我希望它也适用于Jython。

另一种选择是结帐Clojure,其中有多种方法built in