是否可以将方法添加到 Scala 中的内置类型?

Posted

技术标签:

【中文标题】是否可以将方法添加到 Scala 中的内置类型?【英文标题】:Is it possible to add a method to a built-in type in Scala? 【发布时间】:2010-09-22 19:43:05 【问题描述】:

我想为内置类型(例如 Double)添加一个方法,以便我可以使用 infix 运算符。这可能吗?

【问题讨论】:

【参考方案1】:

是的,不是的。是的,你可以让它看起来就像你在double 中添加了一个方法一样。例如:

class MyRichDouble(d: Double) 
  def <>(other: Double) = d != other


implicit def doubleToSyntax(d: Double) = new MyRichDouble(d)

此代码将以前不可用的&lt;&gt; 运算符添加到Double 类型的任何对象。只要doubleToSyntax 方法在范围内,可以在没有限定条件的情况下调用它,以下方法将起作用:

3.1415 <> 2.68     // => true

答案的“否”部分来自于您并没有真正向Double 类添加任何内容。相反,您正在创建从 Double 到确实定义了您想要的方法的新类型的转换。这可能是一种比许多动态语言提供的开放类更强大的技术。它也恰好是完全类型安全的。 :-)

您应该注意的一些限制:

此技术不允许您删除重新定义现有方法,只需添加新方法 隐式转换方法(在本例中为doubleToSyntax)绝对必须在所需扩展方法可用的范围内

通常,隐式转换要么放在单例对象中并导入(例如import Predef._),要么放在特征中并继承(例如class MyStuff extends PredefTrait)。

顺便说一句:Scala 中的“中缀运算符”实际上是方法。 &lt;&gt; 方法没有任何魔法允许它被中缀,解析器只是以这种方式接受它。如果您愿意,也可以使用“常规方法”作为中缀运算符。例如,Stream 类定义了一个take 方法,该方法接受一个Int 参数并返回一个新的Stream。这可以通过以下方式使用:

val str: Stream[Int] = ...
val subStream = str take 5

str take 5 表达式在字面上与 str.take(5) 相同。

【讨论】:

您可以使用implicit class 语法稍微简化一下。【参考方案2】:

这个特性在实现一个执行错误估计的类时派上用场:

object errorEstimation 
  class Estimate(val x: Double, val e: Double) 
    def + (that: Estimate) =
      new Estimate(this.x + that.x, this.e + that.e)
    def - (that: Estimate) =
      new Estimate(this.x - that.x, this.e + that.e)
    def * (that: Estimate) =
      new Estimate(this.x * that.x,
                   this.x.abs*that.e+that.x.abs*this.e+this.e*that.e)
    def / (that: Estimate) =
      new Estimate(this.x/that.x,
                   (this.x.abs*that.e+that.x.abs*this.e)/(that.x.abs*(that.x.abs-that.e)))
    def +- (e2: Double) =
      new Estimate(x,e+e2)
    override def toString =
      x + " +- " + e
  
  implicit def double2estimate(x: Double): Estimate = new Estimate(x,0)
  implicit def int2estimate(x: Int): Estimate = new Estimate(x,0)

  def main(args: Array[String]) = 
    println(((x: Estimate) => x+2*x+3*x*x)(1 +- 0.1))
    // 6.0 +- 0.93
    println(((x: Estimate) => (((y: Estimate) => y*y + 2)(x+x)))(1 +- 0.1))
    // 6.0 +- 0.84
    def poly(x: Estimate) = x+2*x+3/(x*x)
    println(poly(3.0 +- 0.1))
    // 9.33333 +- 0.3242352
    println(poly(30271.3 +- 0.0001))
    // 90813.9 +- 0.0003
    println(((x: Estimate) => poly(x*x))(3 +- 1.0))
    // 27.037 +- 20.931
  

【讨论】:

这实际上有点整洁。 :)

以上是关于是否可以将方法添加到 Scala 中的内置类型?的主要内容,如果未能解决你的问题,请参考以下文章

是否有内置方法可以将字符多次添加到字符串中?

是否可以将方法添加到现有(内置)ActionScript Flash 类而不扩展它并创建一个新类?

你怎么检查drupal 8中的字段是否为空?

使用 Scala 作为 XSLT 的替代品?

高效的方法将键和值添加到scala中的Set Map

Scala隐式参数