一、函数的定义
1、函数定义
(1)函数 1:无参,无返回值
(2)函数 2:无参,有返回值
(3)函数 3:有参,无返回值
(4)函数 4:有参,有返回值
(5)函数 5:多参,无返回值
(6)函数 6:多参,有返回值
2、案例实操
object demo07 {
// (1)函数1:无参,无返回值
def test1(): Unit = {
println("这是无参无返回值的函数")
}
// (2)函数2:无参,有返回值
def test2(): Int = {
42
}
// (3)函数3:有参,无返回值
def test3(num: Int): Unit = {
println(s"传入的参数是: $num")
}
// (4)函数4:有参,有返回值
def test4(num: Int): Int = {
num * 2
}、
// (5)函数5:多参,无返回值
def test5(a: Int, b: Int): Unit = {
println(s"传入的参数是 $a 和 $b")
}
// (6)函数6:多参,有返回值
def test6(a: Int, b: Int): Int = {
a + b
}
def main(args: Array[String]): Unit = {
Test1()
val result2 = test2()
println(s"函数2的返回值: $result2")
test3(5)
val result4 = test4(3)
println(s"函数4的返回值: $result4")
Test5(2, 3)
val result6 = test6(4, 5)
println(s"函数6的返回值: $result6")
}
}
二、函数参数
案例实操:
1、可变参数
2、如果参数列表中存在多个参数,那么可变参数一般放置在最后
3、参数默认值,一般将有默认值的参数放置在参数列表的后面
4、带名参数
object demo08 {
// (1)可变参数
def sumNumbers(numbers: Int*): Int = {
var sum = 0
for (num <- numbers) {
sum += num
}
sum
}
// (2)可变参数放置在最后
def printInfo(name: String, age: Int, hobbies: String*): Unit = {
println(s"姓名: $name,年龄: $age")
println("爱好: " + hobbies.mkString(", "))
}
// (3)参数默认值,有默认值的参数放在后面
def greet(name: String, greeting: String = "Hello"): Unit = {
println(s"$greeting, $name!")
}
// (4)带名参数
def calculate(a: Int, b: Int): Int = {
a + b
}
def main(args: Array[String]): Unit = {
// 测试可变参数
val sumResult = sumNumbers(1, 2, 3, 4, 5)
println(s"可变参数求和结果: $sumResult")
// 测试可变参数放置在最后
printInfo("Alice", 25, "reading", "swimming")
// 测试参数默认值
greet("Bob")
greet("Charlie", "Hi")
// 测试带名参数
val calcResult = calculate(b = 3, a = 2)
println(s"带名参数计算结果: $calcResult")
}
}
三、函数至简原则(重点)
1、至简原则细节
(1)return 可以省略,Scala 会使用函数体的最后一行代码作为返回值
(2)如果函数体只有一行代码,可以省略花括号
(3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
(4)如果有 return,则不能省略返回值类型,必须指定
(5)如果函数明确声明unit,那么即使函数体中使用 return 关键字也不起作用
(6)Scala 如果期望是无返回值类型,可以省略等号
(7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
(8)如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
(9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略
object demo09{
// 体现原则(1)(2)(3)
// return省略,函数体只有一行省略花括号,返回值类型可推断所以省略
def add(a: Int, b: Int) = a + b
// 体现原则(4)
// 有return,明确指定返回值类型
def subtract(a: Int, b: Int): Int = {
return a - b
}
// 体现原则(5)
// 函数声明为Unit,return不起作用
def printResult(result: Int): Unit = {
return println(s"计算结果是: $result")
}
// 体现原则(6)
// 无返回值类型,省略等号
def logMessage(message: String) =println(s"日志: $message")
// 体现原则(7)
// 无参函数声明了参数列表,调用时括号可加可不加
def getSystemInfo(): String = "Scala程序信息"
// 体现原则(8)
// 没有参数列表,调用时括号必须省略
val programVersion = "v1.0"
// 体现原则(9)
// 匿名函数,不关心名称,只关注逻辑
val multiply = (a: Int, b: Int) => a * b
def main(args: Array[String]): Unit = {
val sumResult = add(3, 5)
val diffResult = subtract(5, 3)
printResult(sumResult)
logMessage("执行加法和减法运算")
val info1 = getSystemInfo()
val info2 = getSystemInfo // 调用时括号省略
println(s"系统信息1: $info1,系统信息2: $info2")
println(s"程序版本: $programVersion")
val productResult = multiply(4, 6)
println(s"乘法结果: $productResult")
}
}
四、高阶函数
1、函数可以作为值进行传递
object demo10 {
def calc(): Int = {
println("执行计算操作")
4 + 5
}
def main(args: Array[String]): Unit = {
// (1)调用calc函数,把返回值给变量res
// val res = calc() // 原注释方式
val res = calc
println(res)
// (2)将calc函数整体传递给变量calcFunc
val calcFunc = calc
calc()
calcFunc()
// (3)如果明确变量类型,那么不使用下划线也可以将函数作为整体传递给变量
var anotherCalc: () => Int = calc
}
}
2、函数可以作为参数进行传递
object demo11 {
def main(args: Array[String]): Unit = {
// (1)定义一个函数,函数参数还是一个函数签名;f表示函数名称;(Int, Int)表示输入两个Int参数;Int表示函数返回值
def f1(f: (Int, Int) => Int): Int = {
f(3, 5)
}
// (2)定义一个函数,参数和返回值类型和f1的输入参数一致
def multiply(a: Int, b: Int): Int = {
a * b
}
// (3)将multiply函数作为参数传递给f1函数,如果能够推断出来不是调用,可以省略
println(f1(multiply))
println(f1(multiply _))
// 传递匿名函数
println(f1((x: Int, y: Int) => x - y))
}
}
3、函数可以作为函数返回值返回
object demo12 {
def main(args: Array[String]): Unit = {
// 定义函数f1,它返回一个函数
def f1(): () => Int = {
def f2(): Int = {
println("调用内部函数f2")
42
}
f2
}
// 将f1的返回值赋给变量f
val f = f1()
// 调用f,实际是调用f1返回的f2函数
val result1 = f()
println(s"结果1: $result1")
// 简化写法
val result2 = f1()()
println(s"结果2: $result2")
}
}
五、匿名函数
1、说明
没有名字的函数就是匿名函数。(x:Int)=>{函数体}x:表示输入参数类型;Int:表示输入参数类型;函数体:表示具体代码逻辑2)
2、案例实操:传递的函数有一个参数传递匿名函数至简原则:
(1)参数的类型可以省略,会根据形参进行自动的推导
(2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参数超过 1 的永远不能省略圆括号。
(3)匿名函数如果只有一行,则大括号也可以省略
(4)如果参数只出现一次,则参数省略且后面参数可以用_代替
object demo13 {
def main(args: Array[String]): Unit = {
// 定义一个接收函数作为参数的高阶函数,该参数函数接收一个Int类型参数,返回Int类型结果
def operateOnNumber(num: Int, operation: Int => Int): Int = {
operation(num)
}
// 完整写法的匿名函数
val result1 = operateOnNumber(5, (x: Int) => {
x * x
})
println(s"完整写法结果: $result1")
// 根据原则(1)省略参数类型
val result2 = operateOnNumber(5, (x) => {
x * x
})
println(s"省略参数类型结果: $result2")
// 根据原则(2),只有一个参数时省略圆括号
val result3 = operateOnNumber(5, x => {
x * x
})
println(s"省略圆括号结果: $result3")
// 根据原则(3),函数体只有一行时省略大括号
val result4 = operateOnNumber(5, x => x * x)
println(s"省略大括号结果: $result4")
// 根据原则(4),参数只出现一次时省略参数并用_代替
val result5 = operateOnNumber(5, (x)=> {x * x)})
println(s"参数省略结果: $result5")
}
}
六、函数柯里化&闭包
1、说明
(1)闭包:如果一个函数,访问到了它的外部(局部)变量的值,那么这个函数和他所处的环境,称为闭包
(2)函数柯里化:把一个参数列表的多个参数,变成多个参数列表。
2、案例实操
object demo14 {
def main(args: Array[String]): Unit = {
// 定义函数f1,在其内部定义局部变量和函数
def f1() = {
var num = 5
def f2(x: Int) = {
num + x
}
f2_
}
// 调用f1获取函数f2
val func = f1()
// 调用f2函数并传入参数3
println(func(3))
// 另一种调用方式
println(f1()(3))
}
}
七、递归
1、说明
一个函数/方法在函数/方法体内又调用了本身,我们称之为递归调用
2、案例实操
object demo15{
def main(args: Array[String]): Unit = {
// 计算斐波那契数列第n项,使用递归
def fibonacci(n: Int): Int = {
// 跳出递归的逻辑:第0项和第1项的值
if (n == 0) 0
else if (n == 1) 1
else // 递归调用自身,参数有规律递减
fibonacci(n - 1) + fibonacci(n - 2)
}
println(fibonacci(10))
}
}
八、控制抽象
案例实操:
object demo16 {
def main(args: Array[String]): Unit = {
// 名调用示例:传递代码块
bar({
println("执行名调用代码块")
10
})
// 小括号省略形式的名调用
bar {
println("另一种名调用代码块")
20
}
// 自定义条件循环
var count = 0
myWhile(count < 3) {
println(s"当前count: $count")
count += 1
}
}
// 定义接受名调用参数的函数
def bar(a: => Int): Unit = {
println(s"传入的值: $a")
println(s"再次使用传入的值: $a")
}
// 自定义while循环函数
def myWhile(condition: => Boolean)(block: => Unit): Unit = {
if (condition) {
block
myWhile(condition)(block)
}
}
}
九、惰情加载
1、说明
当函数返回值被声明为 lazy 时,函数的执行将被推迟,直到我们首次对此取值,该函数才会执行。这种函数我们称之为惰性函数
2、案例实操:
object demo17 {
def main(args: Array[String]): Unit = {
// 使用lazy关键字修饰val变量,延迟函数执行
lazy val result = multiply(3, 4)
println("程序在继续执行其他操作...")
println(s"result的值为: $result")
}
def multiply(n1: Int, n2: Int): Int = {
println("multiply函数被执行")
n1 * n2
}
}