Scala系列5:轻松搞定Scala中方法与函数的区别与使用

       Scala 有方法与函数,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法。

  1. 有些翻译上函数(function)与方法(method)是没有区别的,比如都叫函数。
  2. Scala 中的方法跟 Java 的类似,方法是组成类的一部分。
  3. Scala 中的函数则是一个完整的对象,Scala 中的函数其实就是继承了 Trait 的类的对象。
  4. Scala 中使用 val 语句可以定义函数,def 语句定义方法。

0.方法介绍

一个类可以有自己的方法, scala中的方法和Java方法类似。 但scala与Java定义方法的语法是不一样的, 而且scala支持多种调用方式。

1.定义方法
2.方法参数
        *默认参数
        *带名参数
        *变长参数
3.方法返回值类型推断
4.方法调用方式
        *后缀调用法
        *中缀调用法
        *花括号调用法
        *无括号调用法

        

0.1.定义方法

定义方法的语法格式:

def methodName (参数名:参数类型, 参数名:参数类型) : [return type] = {
// 方法体: 一系列的代码
}

特别注意:Scala的语言是极度灵活的
如果方法体函数在{}中,但是没有=,那么它的返回值类型就是Unit,这样的方法被称为过程。比如:
    def  p1(s:String){
      var b = "-"*s.length() + "%\n"
      println(b+s+"\n"+b)
    }
    p1("Hello")
     
    //上下两个方法p1,p2不写返回值与=和写返回值+=的结果一样
    def  p2(s:String):Unit={
      var b = "-"*s.length() + "%\n"
      println(b+s+"\n"+b)
    }
    p2("Hello")

-----%
Hello
-----%

 

尖叫提示:

  1. 参数列表的参数类型不能省略,参数可以多个
  2. 返回值类型可以省略不写,编译器可以自动推断出来,但是对于递归函数,必须指定返回类型
  3. 返回值可以不写return, 默认就是{}的值;

     

//带返回值类型
scala> def sum(x:Int,y:Double):Double=2*x+3*y
sum: (x: Int, y: Double)Double

scala> val s1 = sum(1,2.5)
s1: Double = 9.5

scala> sum(0,2.5)
res0: Double = 7.5
//不带返回值类型,默认根据参数类型推定
scala> def sum1(x:Int,y:Double)= 2*x+3*y
sum1: (x: Int, y: Double)Double

scala> sum1(1,1)
res1: Double = 5.0

//2.注意方法体,带return返回值,也可以不带,不带的话,方法的返回值就是代码块{}的值
    def addInt( a:Int, b:Int ) : Int = {
      var sum:Int = 0
      sum = a + b
      sum;
      //return sum  这个return sum ;跟上面的sum;值一样
    }

    println(addInt(1,2))
    }

0.2.方法参数

scala中的方法参数, 使用比较灵活。 它支持以下几种类型的参数:

  1. 默认参数
  2. 带名参数
  3. 变长参数

0.2.1 默认参数

在定义方法时可以给参数定义一个默认值,这个时候你可以在实际使用这个方法时不传入有默认值的参数。

scala> def s(x:Double,pia:Double=3.14)=pia*x*x
s: (x: Double, pia: Double)Double

scala> s(2,3.1415)
res5: Double = 12.566

scala> s(2)
res6: Double = 12.56

scala> def add(x:Int = 0, y:Int = 0) = x + y
scala>add()
0

0.2.2 带名参数

在调用方法时, 可以指定参数的名称来进行调用。

scala> def s1(x:Double,pia:Double=3.14)=pia*x*x
s1: (x: Double, pia: Double)Double

scala> s1(x=2)
res7: Double = 12.56

scala> s1(2)
res8: Double = 12.56

scala> s1(x=2,pia=3.1415926)
res9: Double = 12.5663704

0.2.3 变长参数

如果方法的参数是不固定的, 可以定义一个方法的参数是变长参数。语法格式如下:

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

//在参数类型后面加一个 * 号, 表示参数可以是0个或者多个
scala> def s3(x:Double*)=x.sum  //这里是调用x的系统内嵌方法sum进行求和
s3: (x: Double*)Double

scala> s3(1,2,3.5,4,5)
res10: Double = 15.5

0.3.方法的返回值类型推断

      比较简单:scala定义方法可以省略返回值, 由scala自动推断返回值类型。 这样方法定义后更加简洁。但是如果是递归函数则需要加入返回值类型

scala> def add(x:Int, y:Int) = x + y
add: (x: Int, y: Int)Int
scala> add(1,2)
res12: Int = 3

0.4.方法调用方式

在scala中, 有以下几种方法调用方式,

  • 后缀调用法
  • 中缀调用法
  • 花括号调用法
  • 无括号调用法

在后续编写spark、 flink程序时, 我们会使用到这些方法。

0.4.1后缀调用法(与Java没有区别)

所谓后缀调用法和中缀调用法的区别就是你可以用下面两种方式调用方法。

  1.  a  方法 b   的形式进行调用,如: 1+2, 1 to 10 
  2. a.方法(b) 的形式进行调用,如,1.+(2), 1.to(10)

语法:对象名.方法名(参数)

scala> Math.max(1,3)
res16: Int = 3

0.4.2 中缀调用法

语法:对象名 方法名 参数

scala> Math max (1,3) //如果有多个参数, 使用括号括起来
res17: Int = 3

0.4.3 花括号调用法

尖叫提示:方法只有一个参数, 才能使用花括号调用法,这个重点关注,后面很常用。

Math.abs{
// 表达式1
// 表达式2
}
//方法只有一个参数, 才能使用花括号调用法

scala> Math.max{1,3}
<console>:1: error: ';' expected but ',' found.
Math.max{1,3}
          ^

scala> Math.abs{-5}
res18: Int = 5

0.4.4 无括号调用法

如果方法没有参数, 可以省略方法名后面的括号

scala> def p() = println("caodan")
p: ()Unit

scala> p()
caodan

1.Scala中函数的使用

函数的语法格式:

val 函数变量名 = (参数名:参数类型, 参数名:参数类型....) => 函数体
 
//函数体用{}包裹起来,其最终值就是代码块最后一个表达式的值


//演示:
scala> val add=(x:Int,y:Int)=> x+y
add: (Int, Int) => Int = <function2>

scala> add(3,6)
res20: Int = 9

//演示2:匿名函数,一般用在参数中
scala> (x:Int,y:Int,z:Double)=> x+y*z
res21: (Int, Int, Double) => Double = <function3>
 
scala> res21(1,2,3)  //res21是系统给匿名函数分配的引用名,可以直接用这个名字调用函数
res22: Double = 7.0

//演示3:函数体在代码块中,则其返回值遵循代码块的原理,是最后一个表达式的值;
scala> (x:Int,y:Int,z:Double)=> {x+y+z;15}
res29: (Int, Int, Double) => Int = <function3>

scala> res29(1,2,3)
res30: Int = 15
scala> res29(132,3,3)
res31: Int = 15

尖叫提示:

  1. 函数是一个对象(变量)
  2. 类似于方法, 函数也有输入参数和返回值
  3. 函数定义不需要使用 def 定义
  4. 无需指定返回值类型
  5. 函数可以是有名字的,也可以是匿名函数。函数定义指定名称,参数 和body{}

2.方法与函数的区别联系

2.1 方法与函数的区别

  1. 方法是隶属于类或者对象的, 在运行时, 它是加载到JVM的方法区中
  2. 可以将函数对象赋值给一个变量, 在运行时, 它是加载到JVM的堆内存中
  3. 函数是一个对象, 继承自FunctionN, 函数对象有apply, curried, toString, tupled这些方法。 方法则没有。
1.方法无法赋值给变量
scala> def add(x:Int,y:Int)=x+y
add: (x: Int, y: Int)Int
scala> val a = add
<console>:12: error: missing argument list for method add
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `add _` or `add(_,_)` instead of `add`.
val a = add

2.方法与函数
scala> def m1(x:Int) = x+3
m1: (x: Int)Int    

scala> val f1 = (x: Int) => x+3
f1: Int => Int = <function1>

Function Type is (roughly) a type of the form (T1, ..., Tn) => U, which is a shorthand for the trait FunctionN in the standard library. Anonymous Functions and Method Values have function types, and function types can be used as part of value, variable and function declarations and definitions. In fact, it can be part of a method type.

Method Type is a non-value type. That means there is no value - no object, no instance - with a method type. As mentioned above, a Method Value actually has a Function Type. A method type is a def declaration - everything about a def except its body.

从上面的例子,得出一个总结:

方法是一个以def开头的带有参数列表(可以无参数列表)的一个逻辑操作块,这正如object或者class中的成员方法一样。

函数是一个赋值给一个变量(或者常量)的匿名方法(带或者不带参数列表),并且通过=>转换符号跟上逻辑代码块的一个表达式。=>转换符号后面的逻辑代码块的写法与method的body部分相同。

 

2.2方法可以转化成函数

  • 有时候需要将方法转换为函数, 作为变量传递, 就需要将方法转换为函数
  • 使用 _ 即可将方法转换为函数
scala> def add(x:Int,y:Int)=x+y
add: (x: Int, y: Int)Int

scala> val a = add _
a: (Int, Int) => Int = <function2>

scala> println(a(1,2))
3

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页