强调 eta 扩展的用法


scala> val names = List("Peter", "Paul", "Mary")
names: List[String] = List(Peter, Paul, Mary)
scala> names.map(_.toUpperCase)
res12: List[String] = List(PETER, PAUL, MARY)

在这种情况下,下划线表示唯一的输入参数,即名称元素。此字符串被隐式转换为 StringOps,并调用 toUpperSame。

但是,这不起作用:

scala> names.map(StringOps.toUpperCase _)
<console>:14: error: value toUpperCase is not a member of object scala.collection.immutable.StringOps
       names.map(StringOps.toUpperCase _)

我认为这种语法是我从 toUpperCase 方法获取对函数的引用的方式。

首先_.toUppercase没有将String转换为StringOps的隐式转换,由于toUppercase属于String类型,因此没有必要转换为StringOps

所以对于_.toUppercase实际上是扩展到高阶函数:val a: String => String = (str: String) => str.toUpperCase .

StringOps Predef.scala 中定义的隐式转换augmentString ,并且这种转换只会在StringOps的方法中使用时才会发生,例如:slicestripSuffixstripPrefix等,例如:

  "name".slice(0, 2)    // convert "name" to new StringOps("name").slice(0,2)
  "name".stringPrefix

StringOps 是一个类,因此要使用它的方法,您需要实例化一个实例:

names.map( x => (new StringOps(x)).toUpperCase )

names.map( new StringOps(_) toUpperCase )

StringOps 是 String 类的包装类,这意味着它使用其他方法(如您正在使用的方法)"丰富"了此类。
当您想在字符串实例上调用方法时,只需执行以下操作:

instanceName.methodName

这正是您在第一个示例中所做的。

但是,在第二个示例中,您将执行以下操作:

methodName(instanceName)

toUpperLetter不接受参数,它是在字符串本身的实例上调用的。

最新更新