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

Itt*_*ayD 18 scala

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

class RichFoo(f: Foo) {
  def newMethod = f.bar()
}
object RichFoo {
  implicit def foo2Rich(f: Foo) = new RichFoo(f)
}
Run Code Online (Sandbox Code Playgroud)

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

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

override class Foo {
  def newMethod = bar
}
Run Code Online (Sandbox Code Playgroud)

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

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

我确定我错过了一些东西,并想深入了解一下.

Mat*_*t R 13

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

2011年10月更新:

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


Dan*_*ral 8

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

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

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

最后要注意的是,如果你想做空,你可以这样做:

implicit def fooBar(f: Foo) = new { def newMethod = bar }
Run Code Online (Sandbox Code Playgroud)

  • `new {...}`是一种结构类型.小心这个:它的方法通过反射调用,这使它变慢.请参阅http://stackoverflow.com/questions/3119580/scala-equivalent-of-csharps-extension-methods/3119671#3119671 (4认同)
  • 我改为导入Foo的覆盖.我没有建议改变课程.我建议将foo.bar转换为com.my.package.Foo.bar(foo).您的上一个示例意味着通过反射调用newMethod (2认同)