理解为什么“pimp my library”在Scala中以这种方式定义

时间:2009-12-16 10:02:33

标签: scala

如果我想在Scala中为类添加方法,我需要执行以下操作:

class RichFoo(f: Foo) {
  def newMethod = f.bar()
}
object RichFoo {
  implicit def foo2Rich(f: Foo) = new RichFoo(f)
}

然后f.newMethod将导致创建RichFoo实例并调用其方法。

我试图理解为什么它没有像Ruby那样定义:

override class Foo {
  def newMethod = bar
}

编译器可以查看此定义,并使用静态方法newMethod创建一个FooOverride类,该方法获取类型为Foo的参数并调用其bar方法。这就是Scala实现特征的方式。我仍然需要导入包含Foo覆盖的包来使用它。

它似乎涉及较少的输入,不需要我创建名称,并且具有更好的性能(不调用方法和创建对象)。隐式转换方法所做的任何事情都可以在附加方法中完成。

我确信我错过了一些东西,并希望深入了解。

2 个答案:

答案 0 :(得分:13)

隐藏转换还有其他用途,而不仅仅是“pimp my library”习惯用法,所以它并不是“为什么他们不这样做呢?”而是“为什么不这样做呢?”好?”。当然,我没有理由不按照你的建议添加扩展方法语法,并且它可能会更清晰,但是由于该语言已经支持一种实现相同效果的方法,因此没有太多迫切需要它。

2011年10月更新:

有一个新建议为此用例添加语法糖:http://scala.github.com/sips/pending/implicit-classes.html

答案 1 :(得分:8)

如何在不需要显式导入并为其命名的情况下阻止该方法进入范围?事实上,如果没有这样做,程序如何知道添加了哪些方法呢?

当您使用三个不同的库时,其中两个以不兼容的方式向第三个库添加方法,如何在不受控制的情况下解决这个问题?

除此之外,由于JVM不允许更改现有类,因此无法获得更好的性能。充其量,您可以获得不必创建名称并且必须以不能控制正在进行的操作为代价来减少打印的好处。

作为最后一点,如果你想做空,你可以这样做:

implicit def fooBar(f: Foo) = new { def newMethod = bar }