下划线这个符号几乎贯穿了任何一本Scala编程书籍,并且在不同的场景下具有不同的含义,绕晕了不少初学者。正因如此,下划线这个特殊符号无形中增加Scala的入门难度。本文希望帮助初学者踏平这个小山坡。

1. 用于替换Java的等价语法

由于大部分的Java关键字在Scala中拥有了新的含义,所以一些基本的语法在Scala中稍有变化。

1.1 导入通配符

*在Scala中是合法的方法名,所以导入包时要使用_代替。

  1.  
    //Java
  2.  
    import java.util.*;
  3.  
     
  4.  
    //Scala
  5.  
    import java.util._

1.2 类成员默认值

Java中类成员可以不赋初始值,编译器会自动帮你设置一个合适的初始值:

  1.  
    class Foo{
  2.  
    //String类型的默认值为null
  3.  
    String s;
  4.  
    }
  5.  
     

而在Scala中必须要显式指定,如果你比较懒,可以用_让编译器自动帮你设置初始值:

  1.  
    class Foo{
  2.  
    //String类型的默认值为null
  3.  
    var s: String = _
  4.  
    }
  5.  
     

该语法只适用于类成员,而不适用于局部变量。

1.3 可变参数

Java声明可变参数如下:

  1.  
    public static void printArgs(String ... args){
  2.  
    for(Object elem: args){
  3.  
    System.out.println(elem + " ");
  4.  
    }
  5.  
    }

调用方法如下:

  1.  
    //传入两个参数
  2.  
    printArgs("a", "b");
  3.  
    //也可以传入一个数组
  4.  
    printArgs(new String[]{"a", "b"});
  5.  
     

在Java中可以直接将数组传给printArgs方法,但是在Scala中,你必须要明确的告诉编译器,你是想将集合作为一个独立的参数传进去,还是想将集合的元素传进去。如果是后者则要借助下划线:

printArgs(List("a", "b"): _*)
 

1.4 类型通配符

Java的泛型系统有一个通配符类型,例如List<?>,任意的List<T>类型都是List<?>的子类型,如果我们想编写一个可以打印所有List类型元素的方法,可以如下声明:

  1.  
    public static void printList(List<?> list){
  2.  
    for(Object elem: list){
  3.  
    System.out.println(elem + " ");
  4.  
    }
  5.  
    }
  6.  
     

对应的Scala版本为:

  1.  
    def printList(list: List[_]): Unit ={
  2.  
    list.foreach(elem => println(elem + " "))
  3.  
    }
  4.  
     

2 模式匹配

2.1 默认匹配

  1.  
    str match{
  2.  
    case "1" => println("match 1")
  3.  
    case _ => println("match default")
  4.  
    }
  5.  
     

2.2 匹配集合元素

  1.  
    //匹配以0开头,长度为三的列表
  2.  
    expr match {
  3.  
    case List(0, _, _) => println("found it")
  4.  
    case _ =>
  5.  
    }
  6.  
     
  7.  
    //匹配以0开头,长度任意的列表
  8.  
    expr match {
  9.  
    case List(0, _*) => println("found it")
  10.  
    case _ =>
  11.  
    }
  12.  
     
  13.  
    //匹配元组元素
  14.  
    expr match {
  15.  
    case (0, _) => println("found it")
  16.  
    case _ =>
  17.  
    }
  18.  
     
  19.  
    //将首元素赋值给head变量
  20.  
    val List(head, _*) = List("a")
  21.  
     

3. Scala特有语法

3.1 访问Tuple元素

  1.  
    val t = (1, 2, 3)
  2.  
    println(t._1, t._2, t._3)

3.2 简写函数字面量(function literal)

如果函数的参数在函数体内只出现一次,则可以使用下划线代替:

  1.  
    val f1 = (_: Int) + (_: Int)
  2.  
    //等价于
  3.  
    val f2 = (x: Int, y: Int) => x + y
  4.  
     
  5.  
    list.foreach(println(_))
  6.  
    //等价于
  7.  
    list.foreach(e => println(e))
  8.  
     
  9.  
    list.filter(_ > 0)
  10.  
    //等价于
  11.  
    list.filter(x => x > 0)
  12.  
     

3.3 定义一元操作符

在Scala中,操作符其实就是方法,例如1 + 1等价于1.+(1),利用下划线我们可以定义自己的左置操作符,例如Scala中的负数就是用左置操作符实现的:

  1.  
    -2
  2.  
    //等价于
  3.  
    2.unary_-

3.4 定义赋值操作符

我们通过下划线实现赋值操作符,从而可以精确地控制赋值过程:

  1.  
    class Foo {
  2.  
    def name = { "foo" }
  3.  
    def name_=(str: String) {
  4.  
    println("set name " + str)
  5.  
    }
  6.  
     
  7.  
    val m = new Foo()
  8.  
    m.name = "Foo" //等价于: m.name_=("Foo")

3.5 定义部分应用函数(partially applied function)

我们可以为某个函数只提供部分参数进行调用,返回的结果是一个新的函数,即部分应用函数。因为只提供了部分参数,所以部分应用函数也因此而得名。

  1.  
    def sum(a: Int, b: Int, c: Int) = a + b + c
  2.  
    val b = sum(1, _: Int, 3)
  3.  
    b: Int => Int = <function1>
  4.  
    b(2) //6

3.6 将方法转换成函数

Scala中方法和函数是两个不同的概念,方法无法作为参数进行传递,也无法赋值给变量,但是函数是可以的。在Scala中,利用下划线可以将方法转换成函数:

  1.  
    //将println方法转换成函数,并赋值给p
  2.  
    val p = println _
  3.  
    //p: (Any) => Unit

4. 小结

下划线在大部分的应用场景中是以语法糖的形式出现的,可以减少击键次数,并且代码显得更加简洁。但是对于不熟悉下划线的同学阅读起来稍显困难,希望通过本文能够帮你解决这个的困惑。

--------------------- 本文来自 CODE男孩 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/qq_24084925/article/details/79041595?utm_source=copy

Scala下划线_使用的更多相关文章

  1. scala中的下划线_

    1.作为“通配符”,类似Java中的*. 例如 import scala.math._ 2.:_*作为一个整体,告诉编译器你希望将某个参数当作参数序列处理! 例如 val s = sum(1 to 5 ...

  2. Scala 神奇的下划线 _

    引言 在 Scala 中,下划线 _ 有很多种用法,作为 Scala 初学者也经常被下划线 _ 搞得晕头转向,下面是对 Scala 中下划线 _ 使用的简单总结~ 导包时, 下划线 _ 表示引用多个方 ...

  3. scala下划线的用法

    1.作为“通配符”,类似Java中的*.如import scala.math._2.:_*作为一个整体,告诉编译器你希望将某个参数当作参数序列处理!例如val s = sum(1 to 5:_*)就是 ...

  4. css命名为何不推荐使用下划线_

    一直习惯了在命名CSS样式名时使用下划线“_”做为单词的分隔符,这也是在写JS时惯用的写法. 用过CSS hack的朋友应该知道,用下划线命名也是一种hack,如使用“_style”这样的命名,可以让 ...

  5. 修改 Pattern代码使 Java 正则表达式支持下划线 '_'

    为什么 由于工作是做数据ETL的,很多时候会使用到正则对数据进行提取,但是java的正则中的groupname不支持'_',官方的文档中是这样的: Group name A capturing gro ...

  6. Python 私有变量中两个下划线 _ _item 与 一个下划线的区别 _item

    python中没有常量的说法, 但是可以通过元组实现一个常量 在python的私有变量中, 存在两个下划线 _ _item 与一个下划线 _item 的区别 前面带两个下划线的私有变量: 只能在本类中 ...

  7. python中有两个下划线__的是内置方法,一个下划线_或者没有下划线的可能是属性,也可能是方法,也可能是类名

    python中有两个下划线__的是内置方法,一个下划线_或者没有下划线的可能是属性,也可能是方法,也可能是类名,如果在类中定义的就是类的私有成员. >>> dir(__builtin ...

  8. 为什么我不建议在C#中用下划线_开头来表示私有字段

    我在C#官方文档的使用属性里看到这种代码: public class Date { private int _month = 7; // Backing store public int Month ...

  9. scala下划线

    作为函数的参数 一个匿名的函数传递给一个方法或者函数的时候,scala会尽量推断出参数类型.例如一个完整的匿名函数作为参数可以写为 scala> def compute(f: (Double)= ...

随机推荐

  1. python 爬虫之 selenium API

    一.浏览器操作 1.浏览器最大化 driver.maximize_window() #将浏览器最大化显示 2.设置浏览器宽.高 driver.set_window_size(480, 800)#设置浏 ...

  2. (C/C++学习笔记) 二十三. 运行时类型识别

    二十三. 运行时类型识别 ● 定义 运行时类型识别(Run-time Type Identification, RTTI) 通过RTTI, 程序能够使用基类的指针或引用来检查(check)这些指针或引 ...

  3. 用matlab绘制中国地图

    reference:https://jingyan.baidu.com/article/870c6fc36fdacfb03ee4be58.html shp: http://muchong.com/ht ...

  4. python day10 参数,命名空间

    一.函数的参数--动态传参 1.动态接收位置参数 1.1在参数位置编写*表示接收任意多个内容 def chi(*food): print("我要吃", food) chi(&quo ...

  5. IE9中input事件与异步事件连用会发生跨域问题

    IE版本中IE8以及IE9以上版本不会存在这个问题唯独IE9 发生跨域问题代码 $("#stock_code").bind("input",function(e ...

  6. 【Python】多线程-3

    #练习:线程等待 Event e.set() e.wait()   from threading import Thread, Lock import threading import time   ...

  7. matlab调用规则变量名eval函数

    eval 函数运用!! 经常会遇到matlab里面有些变量命名其实有一样的规律,,但是不像矩阵这些是可以通过循环来获取的,这个时候就可以利用eval语句了:   首先,假设现在有10个名称类似的变量, ...

  8. [JetBrains注册] 利用教育邮箱注册JetBrains产品(pycharm、idea等)的方法

    我们在使用JetBrains的一些产品时,大多使用网上的一些key去注册或者pojie的,但是由于提供这些key的服务器并不能保证稳定可用,所以可能一段时间我们使用的ide又需要重新pojie. 这里 ...

  9. [转] [Elasticsearch] 数据建模 - 处理关联关系(1)

    [Elasticsearch] 数据建模 - 处理关联关系(1) 标签: 建模elasticsearch搜索搜索引擎 2015-08-16 23:55 6958人阅读 评论(0) 收藏 举报 分类: ...

  10. 第四十一课 KMP子串查找算法

    问题: 右移的位数和目标串没有多大的关系,和子串有关系. 已匹配的字符数现在已经有了,部分匹配值还没有. 前六位匹配成功就去查找PMT中的第六位. 现在的任务就是求得部分匹配表. 问题:怎么得到部分匹 ...