Scala 中下划线的神奇用法
我几天前开始学习Scala。最初,我对Scala中大量使用符号感到困惑。特别是_在不同的场景下有不同的含义,让我一头雾水。经过几天的研究(其实就是各种搜索),我逐渐理解了它的用法,甚至开始喜欢这种语法。好了,让我们来看看Scala中_的各种用法。
"提示" : "我是一个Scala新手"
模式匹配
在Scala中,模式匹配与Java的switch语句有些相似,但功能更强大。
def matchTest(x: Int): String = x match {
case 1 => "一"
case 2 => "二"
case _ => "除了一和二之外的其他值"
}
在Scala中,每个选择器会按照代码中出现的顺序与模式进行匹配,第一个匹配成功的分支会被执行。_在这里充当通配符,可以匹配任何值。Scala支持嵌套模式,所以_也可以嵌套使用。让我们再看一个在嵌套模式中使用_的例子。
expr match {
case List(1,_,_) => "包含三个元素的列表,第一个元素是1"
case List(_*) => "包含零个或多个元素的列表"
case Map[_,_] => "匹配任意键类型和任意值类型的映射"
case _ =>
}
匿名函数
Scala使用优雅的语法来表示匿名函数。_在匿名函数中充当参数的占位符。_只能使用一次,但我们可以使用多个下划线来引用不同的参数。
List(1,2,3,4,5).foreach(print(_))
List(1,2,3,4,5).foreach( a => print(a))
这里的_代表参数。第一种写法是第二种写法的简写形式。让我们再看一个接受两个参数的例子。
val total = List(10,20,30,40,50).reduceLeft(_+_)
val total = List(10,20,30,40,50).reduceLeft((a, b) => a + b)
有一篇很好的文章详细解释了上面这个例子的内部原理。
import导入语句
在Scala中,_在导入包时的作用类似于Java中的*。
// 导入matching包中的所有类
import scala.util.matching._
// 导入Fun对象的所有成员(类似于Java中的静态导入)
import com.example.Fun._
// 导入Fun对象的所有成员,但将Foo重命名为Bar
import com.example.Fun.{ Foo => Bar , _ }
// 导入Fun对象的所有成员,除了Foo。要排除某个成员,可以将其重命名為_
import com.example.Fun.{ Foo => _ , _ }
属性
在Scala中,所有非私有的var都会自动生成getter和setter方法。getter方法名与变量名相同,setter方法名则是变量名加上_=。我们也可以自定义getter和setter。这看起来与Ruby的getter和setter很相似。好,让我们来看一个使用getter和setter的例子。
class Person {
private var _age = 0
def age: Int = _age
def age_=(n: Int): Unit = {
require(n > 0, "年龄必须为正数")
_age = n
}
}
val person = new Person
person.age = 25
println(person.age)
函数
Scala是一门函数式语言,因此我们可以像处理普通变量一样处理函数。如果你想把一个函数赋值给一个新变量,函数会被立即调用,其结果会被赋值给这个变量。这种困惑源于方法调用时可选的花括号。我们需要在函数名后面加上_才能将其赋值给另一个变量。
class Demo {
def calculate = {
// 一些代码
}
val calculateRef = calculate _
}