Scala中的方法&函数的定义

作者:林伟兵,叩丁狼高级讲师。本文为原创文章,转载请注明出处。  

4. 方法&函数的定义

在scala中,函数是一等公民,但是一般在开发中,函数和方法是可以相互代替的。

4.1 方法的定义

  1. 一个完整方法的定义如下

    scala> def add(a:Int, b:Int):Int = {
         | return a+b
         | }
    add: (a: Int, b: Int)Int
    
    scala> add(3,5)
    res1: Int = 8
    
  2. 方法的最后一句为返回值的话,可以将return 去掉, 如果一个方法体只有一句代码,大括号可以去掉。

    scala> def times(x:Int,y:Int) = x * y
    times: (x: Int, y: Int)Int
    
    scala> times(3,5)
    res0: Int = 15
    
  3. 如果一个方法没有返回值,其返回类型为Unit , 并且“=”号可以去掉。

    scala> def log(msg:String){
         | println(msg)
         | }
    log: (msg: String)Unit
    
    scala> log("测试")
    测试
    
  4. 返回值的类型也可以通过智能推导来完成。

4.2 方法转函数的实现

在方法名后加上“ _ ” ,可以将方法转换成函数,如下代码,<function2>表示函数有2个参数,类型都是Int; 并且有 Int 返回值。

在命令行中,系统会将转换好的函数赋值给res5 ; 可以通过res5调用该函数。    
scala> add2 _
res5: (Int, Int) => Int = <function2>

scala> res5(8,8)
res6: Int = 16

4.3 函数的定义

函数的定义可以在方法的基础上进行转换,比如下面代码介绍了函数和方法的定义:

## 方法的定义:def 方法名():ReturnType => {}
scala> def times(x:Int, y:Int) => x*y

## 函数的定义: 去掉了def和方法名 这个代码块需要被别人调用,所以要用一个变量来引用。
scala> val times=(x:Int, y:Int) => x*y
times: (Int, Int) => Int = <function2>

在函数使用过程中,还有另一个常见的操作,就是将函数作为另一个函数的参数来使用,如下代码:

var money =100
def calMoneyLeft():Int = {
    println("函数参数调用中")
    money
}

def cost(x: => Int){
    money -=50
    println("函数参数调用之前")
    println(x)
}

cost(calMoneyLeft())

4.4 可变参数

对于Java来说,可变参数的声明的使用如下:

public class Test {
    public static void foo(String... args){

    }

    public static void bar(int... args){

    }

    //我们常见的main函数就是一个带有可变参数的函数
    public static void main(String... args){
        //可变参数在调用的时候可以传递一个或者多个参数,也可以不传递
        foo("Hello world","Hello Java");
        bar(1,2,3,4);
        bar();
    }
}

scala的可变参数与Java的差不多,只不过把 “…” 改为在类型后面加上“*” 使用如下:

object MultipleArguments {

  def main(args:Array[String]):Unit = {
    println("sum = "+calcSumWithQueue(1,3,5,9,7))
  }

  def calcSumWithQueue(numbers: Int*):Int = {
    var sum = 0
    for (element <- numbers){
      sum+= element
    }
    sum
  }

}

可变参数的位置:

object MultipleArguments {

  //这种写法没毛病
  def foo(arg1: Int,arg2: Double*):Unit = { }

  //可变参数后面不能再出现其他参数
  //def foo2(arg1: Double*,arg2: Int):Unit = { }

  //不允许出现多个类型的可变参数
  //def foo3(arg1: Double*,arg2: Int*):Unit = { }

  //总结:一个函数中只能有一个可变参数,并且只能放在参数列表最后
}

可变参数的传参问题:

object MultipleArguments {

  def main(args: Array[String]): Unit = {
    //可变参数的实参为Range的时候,需要添加:_*来进行数据的转换
    println("sum = " + calcSumWithQueue(1 to 10: _*))
    //可变参数的实参为Array时,需要添加:_*来进行数据的转换
    val arr = Array("Hadoop", "Spark", "Storm")
    printArr(arr: _*)
  }

  def calcSumWithQueue(numbers: Int*): Int = {
    var sum = 0
    for (element <- numbers) {
      sum += element
    }
    sum
  }

  def printArr(arr: String*) {
    arr.foreach(ele => println(ele))
  }
}

4.5 参数的默认值

在函数声明的时候可以为参数设置默认值;在调用的时候将真实的值传递进去,也可以根据参数的名称进行传值:

object ArgWithDefaultVal {

  def main(args: Array[String]):Unit = {
    recordUser()
    recordUser("张三",1.65d)
    //在方法被调用的时候,指定要传入的参数名,这种叫做命名参数
    recordUser(height = 1.55d,name = "李四")
  }

  /*
  *   用户信息的录入
  * */
  def recordUser(name: String="匿名",height: Double=1.70d):Unit = {
    println("录入用户记录 name:"+name+",height:"+height)
  }

}

假如一个方法没有任何参数,那么在调用的时候,括号是可以去掉的。

Scala中的方法&函数的定义