方法的基本语法

image.png

因为方法有返回值,所以可以像变量一样使用。
如:println(方法)

  1. package tcode.chapter05
  2. object $01_MethodDefind {
  3. /**
  4. * 方法的定义基本语法: def 方法名(参数名:类型,....): 返回值类型 = {方法体}
  5. * 方法的方法体的块表达式的结果值类型必须与返回值类型匹配
  6. *
  7. */
  8. def main(args: Array[String]): Unit = {
  9. println(add(10, 20))
  10. }
  11. def add(x:Int,y:Int):Int = {
  12. x+y
  13. }
  14. }

至简原则—定义时

  1. 1、如果方法体只有一行语句,那么方法体的{}省略<br /> 2、如果将方法体的块表达式的结果值作为方法的返回值,那么方法的返回值类型可以省略<br /> 注意:如果方法体中有return关键字,返回值必须定义<br /> 3、如果方法不需要返回值,=可以省略[=与方法体的{}不能同时省略]<br /> 4、如果方法不需要参数,()可以省略<br /> 注意:<br /> 1、如果定义方法的时候没有(),在调用的时候不能带上()<br /> 2、如果定义方法的时候有(),那么在调用的时候()可有可无
  1. package tcode.chapter05
  2. object $02_MethodSample {
  3. def main(args: Array[String]): Unit = {
  4. println(add2(10, 20))
  5. println(add3(10, 20))
  6. //如果定义方法的时候没有(),在调用的时候不能带上()
  7. hello2
  8. //如果定义方法的时候有(),那么在调用的时候()可有可无
  9. hello()
  10. hello
  11. }
  12. //标准形式
  13. def add(x:Int,y:Int):Int = {
  14. x+y
  15. }
  16. // 1、如果方法体只有一行语句,那么方法体的{}省略
  17. def add2(x:Int,y:Int):Int = x+y
  18. //2、如果将方法体的块表达式的结果值作为方法的返回值,那么方法的返回值类型可以省略
  19. def add3(x:Int,y:Int) = {
  20. println("................")
  21. val a = 10
  22. val b =20
  23. x+y+a+b
  24. }
  25. //如果方法体中有return关键字,返回值必须定义
  26. def add4(x:Int,y:Int):Int = {
  27. println("................")
  28. val a = 10
  29. val b =20
  30. return x+y+a+b
  31. }
  32. def printHello(msg:String):Unit = {
  33. println(s"hello:${msg}")
  34. }
  35. //如果方法不需要返回值,=可以省略[=与方法体的{}不能同时省略]
  36. def printHello2(msg:String) { println(s"hello:${msg}") }
  37. def hello():Unit = {
  38. println("hello..............")
  39. }
  40. //4、如果方法不需要参数,()可以省略
  41. def hello2 = println("hello...............")
  42. }

参数:

  1. * 1、默认值参数: def 方法名(参数名:类型=默认值,...):返回值类型 = {...}<br /> * 默认值参数一般放在参数列表最后面<br /> * 2、带名参数: 在调用方法的时候指定将值传递给哪个参数<br /> * 3、可变参数: def 方法名(参数名:类型*):返回值类型 = {...}<br /> * 可变参数不能与默认值参数一起使用<br /> * 可变参数可以与带名参数一起使用<br /> * 如果想要将集合的所有元素传递给可变参数,需要通过 集合名:_* 的方式传递

可变参数作为某函数的返回值的时候,本质上是集合,例如用for将多个可变参数的值返回后就是一个集合
image.png

  1. package tcode.chapter05
  2. import java.time.LocalDateTime
  3. import java.time.format.DateTimeFormatter
  4. object $03_MethodParam {
  5. /**
  6. * @param args
  7. */
  8. def main(args: Array[String]): Unit = {
  9. println(add(10, 20))
  10. println(add())
  11. println(add(100))
  12. println(sum(50))
  13. //带名参数: 在调用方法的时候指定将值传递给哪个参数
  14. println(sum2(y=50))
  15. println(sum3(x=50, z=1, 2, 3, 4, 10, 20, 30))
  16. val paths = getPath(7, "/gmall/user_info")
  17. readFiles(paths:_*)
  18. }
  19. //默认值参数: def 方法名(参数名:类型=默认值,...):返回值类型 = {...}
  20. def add(x:Int=10,y:Int=50):Int = x+y
  21. def sum(y:Int,x:Int=50) = x+y
  22. def sum2(x:Int=50,y:Int) = x+y
  23. //可变参数
  24. def sum3(x:Int,z:Int*) = s"${x}-${z.sum}"
  25. //sum3(10,20,30,40,50)
  26. //需求: 统计前7天的用户登录数
  27. ///gmall/user_info/20210518
  28. ///gmall/user_info/20210517
  29. ///gmall/user_info/20210516
  30. ///gmall/user_info/20210515
  31. ///gmall/user_info/20210514
  32. ///gmall/user_info/20210513
  33. ///gmall/user_info/20210512
  34. //for作为最后一条语句,返回的是一个集合:
  35. def getPath(n:Int,pathPrex:String) = {
  36. //日期操作、jdbc操作、json、http操作
  37. //获取当前日期
  38. val currentTime = LocalDateTime.now()
  39. //获取前N天的日期
  40. for(i <- 1 to n) yield{
  41. val time = currentTime.plusDays(-i)
  42. val timestr = time.format(DateTimeFormatter.ofPattern("yyyyMMdd"))
  43. s"${pathPrex}/${timestr}"
  44. }// n个返回值,对应下面的paths:String*
  45. }
  46. def readFiles(paths:String*) = {
  47. //数据读取
  48. for(path<- paths){
  49. println(path)
  50. }
  51. }
  52. }

函数的基本语法:

image.png

image.png
函数的定义语法: val 函数名 = (参数名:参数类型,…) => { 函数体 } —>函数字面量,就是函数的值,字面量左边就是引用。
函数类型:(参数类型,…)=> 返回值类型

函数的返回值就是函数体块表达式的结果值

函数的简化(相比方法只有一条简化规则): 如果函数体中只有一行语句,那么函数体的{}可以省略

函数作为方法|函数的参数的调用:
image.png

函数在定义方法|函数体内的使用:
image.png

方法就是函数,函数也是对象,函数名就是函数对象的引用,所以调用函数的时候必须带上(),不带上,打印的时候会打印地址
函数就是对象的证明:与变量格式是一致的:
如变量:val name:String = “ldc”,省略变量名后:val name = “ldc”
函数: val add =函数字面量
可以看出格式是一致的
另外:所有函数都是继承Function类
image.png

  1. package tcode.chapter05
  2. object $04_FunctionDefined {
  3. def main(args: Array[String]): Unit = {
  4. println(add(10, 20))
  5. println(add2(10, 20))
  6. println(add4(20,30))
  7. println(hello())
  8. }
  9. val add = (x:Int,y:Int) => {
  10. x+y
  11. }
  12. val add2 = (x:Int,y:Int) => x+y
  13. val hello = () => println("hello...")
  14. val add3 = new Function2[Int,Int,Int] {
  15. //函数体
  16. override def apply(x: Int, y: Int): Int = x+y
  17. }
  18. val name = "zhangsan"
  19. val name2 = name
  20. val add4 = add3
  21. }

函数和方法的区别

方法与参数的区别
1)方法定义在类中可以实现重载,函数不可以重载
2)方法是保存在方法区,函数是保存在堆中
3)定义在方法中的方法可以称之为函数,不可以重载,函数是对象,函数名就是变量名,所以函数不可以重载[同一作用域不可以有同名变量]
方法与函数的联系
1)方法可以转成函数, 转换语法: 方法名 _
2)方法可以定义在任何位置,如果定义在方法内(同一作用域,如main方法内),此时就是函数、变量,也就是说不可以重载

  1. package tcode.chapter05
  2. object $05_MethodAndFunction {
  3. def main(args: Array[String]): Unit = {
  4. add(10,20,30)
  5. val func2 = printHello _
  6. func2("haha")
  7. def sum(x:Int,y:Int) = x+y
  8. // def sum(x:Int,y:Int,z:Int) = x+y+z
  9. println(sum(10, 20))
  10. }
  11. val func = (x:Int,y:Int) =>x+y
  12. //val func = (x:Int,y:Int,z:Int) =>x+y+z
  13. def add(x:Int,y:Int) = x+y
  14. def add(x:Int,y:Int,z:Int) = x+y+z
  15. def printHello(msg:String) = println(msg)
  16. }

高阶函数

  1. 定义:参数为函数的方法/函数称为高阶函数

高阶函数简写—调用时

//1、直接将函数值作为参数传递给高阶函数
image.png
//2、函数字面量的参数类型可以省略

  1. //1、直接将函数值作为参数传递给高阶函数
  2. println(add(10, 20, (x: Int, y: Int) => x * y))
  3. //2、函数的参数类型可以省略
  4. println(add(10, 20, (x, y) => x + y))

//3、如果函数的参数在函数体中只使用了一次,那么可以用代替
1、函数的参数的使用顺序与定义顺序不一致,不可以用
代替<针对函数的参数有多个的情况>
image.png
2、如果函数体中有嵌套[()],函数的参数在函数体的嵌套中以表达式的形式存在,不可以用_代替
如:

  1. println(add(10, 20, (x, y) => (x + 10) * y)) 不可以
  2. println(add(10, 20, (x, y) => (x) * y)) 可以
  1. 3、如果函数只有一个参数,在函数体中直接返回参数,此时不可以用_代替<针对函数的只有一个参数的情况>
  1. val f = (x: Int) => x + 10 不可
  2. val f = x=>x 不可

//4、如果函数只有一个参数,函数的()可以省略

  1. package tcode.chapter05
  2. object $07_HightFunctionSample {
  3. def main(args: Array[String]): Unit = {
  4. val func = (x: Int, y: Int) => x * y
  5. val func2 = (x: String, y: Int) => x * y
  6. val name = "zhagnsan"
  7. println(add(10, 20, func))
  8. //1、直接将函数值作为参数传递给高阶函数
  9. println(add(10, 20, (x: Int, y: Int) => x * y))
  10. //2、函数的参数类型可以省略
  11. println(add(10, 20, (x, y) => x + y))
  12. //3、如果函数的参数在函数体中只使用了一次,那么可以用_代替
  13. // 1、函数的参数的使用顺序与定义的顺序不一致,不可以用_代替<针对函数的参数有多个的情况>
  14. // 2、如果函数体中有嵌套[()],函数的参数在函数体的嵌套中以表达式的形式存在,不可以用_代替
  15. // 3、如果函数只有一个参数,在函数体中直接返回参数,此时不可以用_代替<针对函数的只有一个参数的情况>
  16. println(add(10, 20, _ + _))
  17. //3.1 函数的参数的使用顺序与定义的顺序不一致,不可以用_代替
  18. println(add(10, 20, (x, y) => y - x))
  19. println(add(10, 20, _ - _))
  20. //3.2 如果函数体中有嵌套,函数的参数在函数体的嵌套中以表达式的形式存在,不可以用_代替
  21. println(add(10, 20, (x, y) => (x + 10) * y))
  22. //println(add(10, 20, ( _+10 ) *_ ))
  23. //( _+10 ) *_ ) 解析成 y=> (x=>x+10) * y
  24. //( _+10 ) 解析成 x=>x+10
  25. // 如果函数体中有嵌套,但是函数的参数在嵌套中不以表达式存在的时候,可以用_代替的
  26. println(add(10, 20, (x, y) => (x + 10) * y))
  27. println(add(10, 20, _ * _))
  28. //3.3 如果函数只有一个参数,在函数体中直接返回参数,此时不可以用_代替
  29. val f = (x: Int) => x + 10
  30. m1(10, f)
  31. //直接传递函数值
  32. println(m1(10, (x: Int) => x + 10))
  33. //函数参数类型可以省略
  34. println(m1(10, (x) => x + 10))
  35. // 使用_代替
  36. println(m1(10, _ + 10))
  37. println(m1(10, x => x))
  38. //不能简化
  39. println(m1(10, _))
  40. //m1(10,_ )解析的形式:
  41. val m2 = (func: (Int) => Int) => func(10)
  42. m2(x => x + 1)
  43. val func3 = m1(10, _)
  44. //m1(10,_ )
  45. //4、如果函数只有一个参数,函数的()可以省略
  46. println(m1(10, (x) => x + 10))
  47. println(m1(10, x => x + 10))
  48. }
  49. //高阶函数!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  50. def add(x: Int, y: Int, func: (Int, Int) => Int) = func(x, y)
  51. def m1(x: Int, func: Int => Int) = func(x)
  52. }

匿名函数

1)说明
没有名字的函数就是匿名函数,
可以直接通过函数字面量(λ表达式)来设置匿名函数,函数字面量定义格式如下。

2)案例实操

  1. package tcode.chapter05
  2. object $13_NoNameFunction {
  3. /**
  4. * 匿名函数的定义: 没有函数名的函数称之为匿名函数
  5. * 匿名函数不能单独调用
  6. * 匿名函数一般是作为值传递给高级函数使用
  7. */
  8. def main(args: Array[String]): Unit = {
  9. val func = (x:Int,y:Int) => x+y
  10. println(func(20, 30))
  11. //(x:Int,y:Int) => x+y
  12. m1(10,20,(x:Int,y:Int) => x+y)
  13. }
  14. def m1(x:Int,y:Int,func: (Int,Int)=>Int) = func(x,y)
  15. }

柯里化

  1. def m1(x:Int,y:Int,z:Int) = x+y+z
  2. //柯里化
  3. def m2(x:Int)(y:Int)(z:Int) = x+y+z

package tcode.chapter05

object $14_Currying {

/*
柯里化: 有多个参数列表的方法称之为柯里化
*/
def main(args: Array[String]): Unit = {

  1. println(m2(10)(20)(30))
  2. val func = m3(10)
  3. val func2 = func(20)<br /> val r = func2(30)
  4. println(r)
  5. m3(10)(20)(30)
  6. val func3 = m2 _<br /> val func4 = m3 _<br /> }

def m1(x:Int,y:Int,z:Int) = x+y+z
//柯里化
def m2(x:Int)(y:Int)(z:Int) = x+y+z

//柯里化的演变
def m3(x:Int) = {

  1. val func = (y:Int) =>{
  2. val func2 = (z:Int) => x+y+z
  3. func2<br /> }
  4. func<br /> }

}

闭包

package tcode.chapter05
object $15_ClosePackage {
/*
闭包: 函数体中使用了外部变量的函数
@param args
/
def main(args: Array[String]): Unit = {
println(func(10))
}
val y = 10
//闭包
val func = (x:Int) => {
val z = 10
x+y
}
}

递归

package tcode.chapter05

object $16_Recursion {

/*
递归: 自己调用自己
满足两个条件才能称之为递归:
1、必须要有退出条件
2、必须定义返回值类型
定义递归函数的时候必须指定函数的类型
*/
def main(args: Array[String]): Unit = {

  1. println(m1(5))<br /> println(func(5))<br /> }

val func:Int=>Int = (n:Int) => {
if(n==1) 1
else n * func(n-1)
}

def m1( n:Int ):Int = {
if( n ==1 ) 1
else n * m1(n-1)
}
}

惰性

package tcode.chapter05

object $17_Lzy {

/*
惰性求值: 变量不会立即初始化而是等到真正使用的时候才会初始化
语法: lazy val 变量名 = 值
@param args
*/
def main(args: Array[String]): Unit = {

  1. lazy val name = "zhangsan"
  2. println(name)
  3. println("---------------")

}
}

控制抽象

空格=> 返回值类型
package tcode.chapter05

object $18_ControlAbstract {

/*
控制抽象:
用途: 只能作为方法的参数存在,不能单独使用
语法: 代码块没有标志符,所以没有类型,模仿函数,用空格代替标志符及其类型: 空格=> 返回值类型
控制抽象其实就是一个块表达式,=> 返回值类型 代表快表达式的结果值类型必须是指定类型
本质:没有参数的函数
*/
def main(args: Array[String]): Unit = {

  1. var e =1
  2. while(e<=10){<br /> println(s"e=${e}")<br /> e=e+1<br /> 10<br /> }
  3. e = 1<br />// 调用: 控制参数就是代码块<br /> myWhile({<br /> e<=10<br /> })({<br /> println(s"e=${e}")<br /> e=e+1<br /> 10<br /> })<br /> }<br />//定义: 由参数可看出是控制抽象<br /> def myWhile(condition: => Boolean)(loop: => Unit):Unit = {
  4. if(condition){<br /> loop<br /> myWhile(condition)(loop)<br /> }

}