4

我经常面临想要向我无法控制的类添加其他方法的问题。例如,我可能想要一个prettyPrint可以对没有统一 api 的不同对象类型(例如特殊__str__方法)进行操作的函数。

Nice语言R使用多种方法来实现这一点,很好地避免了访问者模式。例如,R具有plot()功能。个别程序员可以创建新类来定义数据类型(例如,网络图或股票行情数据)。次要用户/程序员然后可以编写绘图函数来填充该功能,即使他们无法访问图形或股票代码或其他绘图函数的代码。

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

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

4

4 回答 4

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

不能做的是向对象动态添加方法(即,在运行时而不是编译时)。在第一种情况下,您说的是“将此方法添加到此类”。在第二种情况下,您说的是“创建具有此特征的对象”。这些都可以,但“将此方法添加到此对象”不是。

于 2009-08-24T22:00:41.630 回答
1

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

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

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

我还假设您不想修补类,这在技术上也是可行的(尽管不建议这样做)。

于 2009-08-24T19:56:44.187 回答
1

Scala 有Implicits的概念。这是一个类比 C# 的扩展方法

于 2009-08-24T20:04:36.590 回答
1

如果您不想自己实现多方法,可以使用 Python的多方法打包实现。我希望它也适用于 Jython。

另一种选择是查看具有内置多方法的Clojure

于 2009-08-25T07:29:31.447 回答