Spark 3.x大数据分析实战(视频教学版)
上QQ阅读APP看书,第一时间看更新

1.3.5 方法与函数

Scala中有方法与函数。Scala方法是类或对象中定义的成员,而函数是一个对象,可以将函数赋值给一个变量。换句话说,方法是函数的特殊形式。

1.方法

Scala中的方法跟Java的类似,方法是组成类的一部分。Scala中方法的定义使用def关键字,语法如下:

    def 方法名 (参数列表):返回类型={
       方法体
    }

例如以下代码,将两个数字求和然后返回,返回类型为Int:

    def addNum( a:Int, b:Int ) : Int = {
          var sum = 0
          sum = a + b
       return sum
    }

只要方法不是递归的,可以省略返回类型,系统会自动推断返回类型,并且返回值默认是方法体的最后一行表达式的值。当然也可以用return来执行返回值,但Scala并不推荐。

因此,可以对上面的代码进行简写,去掉返回类型和return关键字,代码如下:

    def addNum( a:Int, b:Int ) = {
         var sum = 0
         sum = a + b
         sum
    }

方法的调用与Java相同,代码如下:

    addNum(1,2)

如果方法没有返回结果,那么可以将返回类型设置为Unit,类似Java中的void,代码如下:

    def addNum( a:Int, b:Int ) : Unit = {
         var sum = 0
         sum = a + b
         println(sum)
    }

在定义方法参数时,可以为某个参数指定默认值,在方法被调用时可以不为带有默认值的参数传入实参。例如以下方法,指定参数a的默认值为5:

    def addNum( a:Int=5, b:Int ) = {
         var sum = 0
         sum = a + b
         sum
    }

上述方法可以用如下代码调用,通过指定参数名称,只传入参数b:

    addNum(b=2)

也可以将a、b两个参数都传入:

    addNum(1,2)

需要注意的是,当未被指定默认值的参数不是第一个时,参数名称不能省略。例如下面的调用是错误的:

    addNum(2)//错误调用

当方法需要多个相同类型的参数时,可以指定最后一个参数为可变长度的参数列表,只需要在最后一个参数的类型之后加一个星号即可。例如以下方法,参数b可以是0到多个Int类型的参数:

    def addData( a:String,b:Int* ) = {
        var res=0
         for (i <- b)
           res=res+i
         a+res
    }

在方法内部,重复参数的类型实际上是一个数组。因此,上述方法中的参数b的类型实际上是一个Int类型的数组,即Array[Int]。可以使用如下代码对上述方法进行调用:

    val res=addData("hello",3,4,5)
    println(res)

输出结果为:hello12。

但是如果直接向方法addData()传入一个Int类型的数组,编译器反而会报错:

    val arr=Array(3,4,5)
    val res=addData("hello",arr)//此写法不正确
    println(res)

此时需要在数组参数后添加一个冒号和一个_*符号,以告诉编译器分别把数组arr的每个元素当作参数,而不是将数组当作单一的参数传入,代码如下:

    val arr=Array(3,4,5)
    val res=addData("hello",arr:_*)
    println(res)

输出结果同样为:hello12。

2.函数

函数的定义与方法不一样,语法如下:

    (参数列表)=>函数体

例如以下代码定义了一个匿名函数,参数为a和b,且都是Int类型,函数体为a+b,返回类型由系统自动推断,推断方式与方法相同:

    ( a:Int, b:Int ) =>a+b

如果函数体有多行,就可以将函数体放入一对{}中,并且可以通过一个变量来引用函数,变量相当于函数名称,代码如下:

    val f1=( a:Int, b:Int ) =>{ a+b }

此时可以通过如下代码对其进行调用:

    f1(1,2)

当然,函数也可以没有参数,代码如下:

    val f2=( ) =>println("hello scala")

此时可以通过如下代码对其进行调用:

    f2()

3.方法与函数的区别

方法与函数的区别有以下三点:

(1)方法是类的一部分,而函数是一个对象并且可以赋值给一个变量。

(2)函数可以作为参数传入方法中。

例如,定义一个方法m1,参数f要求是一个函数,该函数有两个Int类型的参数,且函数的返回类型为Int,在方法体中直接调用该函数,代码如下:

    def m1(f: (Int, Int) => Int): Int = {
      f(2, 6)
     }

定义一个函数f1,代码如下:

    val f1 = (x: Int, y: Int) => x + y

调用方法m1,并传入函数f1:

    val res = m1(f1)
    println(res)

此时输出结果为8。

(3)方法可以转换为函数。当把一个方法作为参数传递给其他的方法或者函数时,系统会自动将该方法转换为函数。

例如,有一个方法m2,代码如下:

    def m2(x:Int,y:Int) = x+y

调用上面的m1方法,并将m2作为参数传入,此时系统会自动将m2方法转为函数:

    val res = m1(m2)
    println(res)

此时输出结果为8。

除了系统自动转换外,也可以手动进行转换。在方法名称后加一个空格和一个下划线,即可将方法转换为函数。代码如下:

    //将方法m2转换为函数
    val f2=m2 _
    val res=m1(f2)
    println(res)

此时输出结果仍然为8。