Scala基础 - 下划线使用指南
下划线这个符号几乎贯穿了任何一本Scala编程书籍,并且在不同的场景下具有不同的含义,绕晕了不少初学者。正因如此,下划线这个特殊符号无形中增加Scala的入门难度。本文希望帮助初学者踏平这个小山坡。
1. 用于替换Java的等价语法
由于大部分的Java关键字在Scala中拥有了新的含义,所以一些基本的语法在Scala中稍有变化。
1.1 导入通配符
*在Scala中是合法的方法名,所以导入包时要使用_代替。
//Java
import java.util.*;
//Scala
import java.util._
1.2 类成员默认值
Java中类成员可以不赋初始值,编译器会自动帮你设置一个合适的初始值:
class Foo{
//String类型的默认值为null
String s;
}
而在Scala中必须要显式指定,如果你比较懒,可以用_让编译器自动帮你设置初始值:
class Foo{
//String类型的默认值为null
var s: String = _
}
该语法只适用于类成员,而不适用于局部变量。
1.3 可变参数
Java声明可变参数如下:
public static void printArgs(String ... args){
for(Object elem: args){
System.out.println(elem + " ");
}
}
调用方法如下:
//传入两个参数
printArgs("a", "b");
//也可以传入一个数组
printArgs(new String[]{"a", "b"});
在Java中可以直接将数组传给printArgs方法,但是在Scala中,你必须要明确的告诉编译器,你是想将集合作为一个独立的参数传进去,还是想将集合的元素传进去。如果是后者则要借助下划线:
printArgs(List("a", "b"): _*)
1.4 类型通配符
Java的泛型系统有一个通配符类型,例如List<?>,任意的List类型都是List<?>的子类型,如果我们想编写一个可以打印所有List类型元素的方法,可以如下声明:
public static void printList(List<?> list){
for(Object elem: list){
System.out.println(elem + " ");
}
}
对应的Scala版本为:
def printList(list: List[_]): Unit ={
list.foreach(elem => println(elem + " "))
}
2 模式匹配
2.1 默认匹配
str match{
case "1" => println("match 1")
case _ => println("match default")
}
2.2 匹配集合元素
//匹配以0开头,长度为三的列表
expr match {
case List(0, _, _) => println("found it")
case _ =>
}
//匹配以0开头,长度任意的列表
expr match {
case List(0, _*) => println("found it")
case _ =>
}
//匹配元组元素
expr match {
case (0, _) => println("found it")
case _ =>
}
//将首元素赋值给head变量
val List(head, _*) = List("a")
3. Scala特有语法
3.1 访问Tuple元素
val t = (1, 2, 3)
println(t._1, t._2, t._3)
3.2 简写函数字面量(function literal)
如果函数的参数在函数体内只出现一次,则可以使用下划线代替:
val f1 = (_: Int) + (_: Int)
//等价于
val f2 = (x: Int, y: Int) => x + y
list.foreach(println(_))
//等价于
list.foreach(e => println(e))
list.filter(_ > 0)
//等价于
list.filter(x => x > 0)
3.3 定义一元操作符
在Scala中,操作符其实就是方法,例如1 + 1等价于1.+(1),利用下划线我们可以定义自己的左置操作符,例如Scala中的负数就是用左置操作符实现的:
-2
//等价于
2.unary_-
3.4 定义赋值操作符
我们通过下划线实现赋值操作符,从而可以精确地控制赋值过程:
class Foo {
def name = { "foo" }
def name_=(str: String) {
println("set name " + str)
}
val m = new Foo()
m.name = "Foo" //等价于: m.name_=("Foo")
3.5 定义部分应用函数(partially applied function)
我们可以为某个函数只提供部分参数进行调用,返回的结果是一个新的函数,即部分应用函数。因为只提供了部分参数,所以部分应用函数也因此而得名。
def sum(a: Int, b: Int, c: Int) = a + b + c
val b = sum(1, _: Int, 3)
b: Int => Int = <function1>
b(2) //6
3.6 将方法转换成函数
Scala中方法和函数是两个不同的概念,方法无法作为参数进行传递,也无法赋值给变量,但是函数是可以的。在Scala中,利用下划线可以将方法转换成函数:
//将println方法转换成函数,并赋值给p
val p = println _
//p: (Any) => Unit
4. 小结
下划线在大部分的应用场景中是以语法糖的形式出现的,可以减少击键次数,并且代码显得更加简洁。但是对于不熟悉下划线的同学阅读起来稍显困难,希望通过本文能够帮你解决这个的困惑。本文成文仓促,如有遗漏,欢迎留言! 转载请注明作者: joymufeng
Scala基础 - 下划线使用指南的更多相关文章
- scala的下划线
1.作为“通配符”,类似Java中的*.如import scala.math._ 2.:_*作为一个整体,告诉编译器你希望将某个参数当作参数序列处理!例如val s = sum(1 to 5:_*)就 ...
- Scala中 下划线的用处
From: http://congli.iteye.com/blog/2169401 1.作为“通配符”,类似Java中的*.如import scala.math._ 2.:_*作为一个整体,告诉 ...
- Scala _ 下划线
1.引入包中的全部方法 import math._ //引入包中所有方法,与java中的*类似 2.表示集合元素 val a = (1 to 10).filter(_%2==0).map(_*2) / ...
- scala下划线
作为函数的参数 一个匿名的函数传递给一个方法或者函数的时候,scala会尽量推断出参数类型.例如一个完整的匿名函数作为参数可以写为 scala> def compute(f: (Double)= ...
- scala 基础语法
文章内容全部来自:http://twitter.github.io/scala_school/zh_cn/index.html 表达式 scala> 1 + 1 res0: Int = 2 值 ...
- 【转】Scala基础知识
原文地址.续 课程内容: 关于这节课 表达式 值 函数 类 继承 特质 类型 apply方法 单例对象 函数即对象 包 模式匹配 样本类 try-catch-finally 关于这节课 最初的几个星期 ...
- scala中的下划线_
1.作为“通配符”,类似Java中的*. 例如 import scala.math._ 2.:_*作为一个整体,告诉编译器你希望将某个参数当作参数序列处理! 例如 val s = sum(1 to 5 ...
- Scala下划线_使用
下划线这个符号几乎贯穿了任何一本Scala编程书籍,并且在不同的场景下具有不同的含义,绕晕了不少初学者.正因如此,下划线这个特殊符号无形中增加Scala的入门难度.本文希望帮助初学者踏平这个小山坡. ...
- Scala中_(下划线)的常见用法
Scala中_(下划线)的常见用法 地址:https://www.jianshu.com/p/0497583ec538
随机推荐
- Shell常见用法小记
shell的简单使用 最近发现shell脚本在平常工作中简直算一把瑞士军刀,很多场景下用shell脚本能实现常用的简单需求,而之前都没怎么学习过shell,就趁机把shell相关的语法和常见用法总结了 ...
- Oeacle创建表空间
/*第1步:创建临时表空间 */ create temporary tablespace user_temp tempfile 'D:\oracle\oradata\Oracle9i\user_tem ...
- Linux ubuntu 安装gcc、g++、 pcre、zlib、ssl、nginx和该内存不能为written解决方法
1.楼主也是第一次接触Linux 如果有错误的地方还请各位朋友指出.... 2.gcc.g++依赖库:sudo apt-get install build-essential,sudoapt-get ...
- SqlParameter参数类型为int32时候的传值陷阱
前2天在使用SqlParameter传递参数的时候遇到一个小坑,这里分享一下. SqlParameter para=new SqlParameter("@IsDeleted",0) ...
- CSS3-渐变背景色
线性渐变背景色: <style> .linear { width:130px; height:130px; border:2px solid black; padding: 10px; b ...
- Xamarin.Forms+Prism(1)—— 开发准备
本次随笔连载,主要用于记录本人在项目中,用Xamarin.Forms开发APP中所使用的第三方技术或一些技巧. 准备: 1.VS2017(推荐)或VS2015: 2.JDK 1.8以上: 3.Xama ...
- .exe简单的更新软件demo
百度网盘源码加文件:http://pan.baidu.com/s/1qYe2Vgg 功能:通过网站更新用户的软件,需要联网,也可以通过本地网站更新局域网用户软件. 根本实现:1.一个网站(本地就可以) ...
- js中字符串转换为日期型
简介:字符串转日期型函数 传入一个字符串格式的日期,如何转换为日期型的.以下为转换方案. //字符串转换为日期函数,返回日期型(传入的日期格式2014-04-22) function StringTo ...
- 【HDOJ 2150】线段交叉问题
Pipe Time Limit : 1000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Submissi ...
- webapp 1px显示两倍的问题
公司最近换新首页,按照设计师的要求<大家都在逛>的分割线要1个像素. .span-3{ width:33.3333%; &:not(:first-child){ &:bef ...