【问题标题】:Understanding why "pimp my library" was defined that way in Scala理解为什么在 Scala 中以这种方式定义“pimp my library”
【发布时间】:2009-12-16 10:02:32
【问题描述】:

如果我想在 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 覆盖的包才能使用它。

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

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

【问题讨论】:

  • 在这种情况下,Ruby 的性能真的优于 Scala,还是您推测开放类实现可以像封闭类一样快?
  • 我建议一个外观,看起来像是在重新打开一个类,但实际上只是调用静态方法。 scala 编译器一直在做这样的事情(特征被编译成一个接口和一个带有静态方法的类)。我推测与当前的隐式defs方式相比,它的编码更少,速度更快

标签: scala


【解决方案1】:

除了“pimp my library”习语之外,隐式转换还有其他用途,所以这并不是“他们为什么不这样做?”,而是“他们为什么不这样做?好?”。当然,我看不出为什么不能按照您的建议添加扩展方法语法,而且它可能会更干净一些,但鉴于该语言已经支持实现相同效果的方法,因此没有太大的迫切需要.

2011 年 10 月更新:

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

【讨论】:

【解决方案2】:

如何在不需要显式导入并为其命名的情况下防止该方法进入作用域?实际上,程序不这样做怎么能知道添加了哪些方法呢?

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

除此之外,不可能有更好的性能,因为 JVM 不允许更改现有类。充其量,您可以获得不必发明名称和减少输入的好处,但代价是无法控制正在执行的操作。

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

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

【讨论】:

  • 我改为导入 Foo 的覆盖。我不建议改变班级。我建议将 foo.bar 转换为 com.my.package.Foo.bar(foo)。您的最后一个示例意味着通过反射调用 newMethod
  • new { ... } 是一种结构类型。注意这一点:它的方法是通过反射调用的,这使得它变慢了。见stackoverflow.com/questions/3119580/…
猜你喜欢
  • 1970-01-01
  • 2012-05-11
  • 2021-11-11
  • 2021-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多