目录
一、函数基础
1)面向对象编程
解决问题,分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题。
对象:用户;
行为:登录、连接jdbc、读取数据库
属性:用户名、密码
Scala语言是一个完全面向对象编程语言。万物皆对象
2)函数式编程
解决问题时,将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用这些封装好的步骤,解决问题。
例如:请求->用户名、密码->连接jdbc->读取数据库
Scala语言是一个完全函数式编程语言。万物皆函数
3)在Scala中函数式编程和面向对象编程融合在一起了。
1、函数的基本语法
1)基本语法
2)案例实操
需求:定义一个方法,实现将传入的名称打印出来。
object TestFunction {
def main(args: Array[String]): Unit = {
// 1 方法声明
def f(arg: String): Unit = {
println(arg)
}
// 2 方法调用
// 方法名(参数)
f("hello world")
}
}
2、函数的方法的区别
1)方法定义在类中可以实现重载,函数不可以重载
2)方法是保存在方法区,函数是保存在堆中
3)定义在方法中的方法可以称之为函数,不可以重载
4)方法可以转成函数, 转换语法: 方法名
object TestFunction {
//方法可以进行重载和重写,程序可以执行
def main(): Unit = {
}
//定义一个方法
def add(x:Int,y:Int) = x+y
def main(args: Array[String]): Unit = {
//Scala语言的语法非常灵活,可以在任何的语法结构中声明任何的语法
import java.util.Date
new Date()
//函数没有重载和重写的概念,程序报错
val test =()=> {
println("无参,无返回值")
}
test()
val test = (name:String)=>{
println()
}
//(3)scala中函数可以嵌套定义
val test2 = ()=>{
val test3 = (name:String)=>{
println("函数可以嵌套定义")
}
}
//(4) 方法可以转成函数
val add2 = add _
}
}
3、函数定义
1)方法声明
(1)方法1:无参,无返回值
(2)方法2:无参,有返回值
(3)方法3:有参,无返回值
(4)方法4:有参,有返回值
(5)方法5:多参,无返回值
2)案例实操
package com.test.chapter06
object TestFunctionDeclare {
def main(args: Array[String]): Unit = {
// 方法1:无参,无返回值
def test(): Unit ={
println("无参,无返回值")
}
test()
// 方法2:无参,有返回值
def test2():String={
return "无参,有返回值"
}
println(test2())
// 方法3:有参,无返回值
def test3(s:String):Unit={
println(s)
}
test3("jinlian")
// 方法4:有参,有返回值
def test4(s:String):String={
return s+"有参,有返回值"
}
println(test4("hello "))
// 方法5:多参,无返回值
def test5(name:String, age:Int):Unit={
println(s"$name, $age")
}
test5("dalang",40)
}
}
4、函数参数
1)案例实操
(1)可变参数
(2)如果参数列表中存在多个参数,那么可变参数一般放置在最后
(3)参数默认值
(4)带名参数
object TestFunction {
def main(args: Array[String]): Unit = {
// (1)可变参数
def test( s : String* ): Unit = {
println(s)
}
// 有输入参数:输出 Array
test("Hello", "Scala")
// 无输入参数:输出List()
test()
// (2)如果参数列表中存在多个参数,那么可变参数一般放置在最后
def test2( name : String, s: String* ): Unit = {
println(name + "," + s)
}
/*
可变参数一般放置在最后
def test2( s: String*,name : String ): Unit = {
println(name + "," + s)
}
*/
test2("jinlian", "dalang")
// (3)参数默认值
def test3( name : String, age : Int = 30 ): Unit = {
println(s"$name, $age")
}
// 如果参数传递了值,那么会覆盖默认值
test3("jinlian", 20)
// 如果参数有默认值,在调用的时候,可以省略这个参数
test3("dalang")
def test4( sex : String = "男", name : String ): Unit = {
println(s"$name, $sex")
}
// scala函数中参数传递是,从左到右
// 一般情况下,将有默认值的参数放置在参数列表的后面
// test4("wusong")
//(4)带名参数
test4(name="ximenqing")
}
}
5、函数至简原则
方法至简原则:能省则省
1)至简原则细节
(1)return可以省略,Scala会使用方法体的最后一行代码作为返回值
(2)如果方法体只有一行代码,可以省略花括号
(3)返回值类型如果能够推断出来,那么可以省略
(4)如果方法无参,则可以省略小括号。若定义方法时省略小括号,则调用该方法时,也需省略小括号;若定时方法时未省略,则调用时,可省可不省。
(5)如果方法明确声明Unit,那么即使方法体中使用return关键字也不起作用
(6)Scala如果想要自动推断无返回值,可以省略等号
(7)如果方法明确使用return关键字,那么方法返回就不能使用自行推断了,需要声明返回值类型
(8)如果不关系名称,只关心逻辑处理时,那么函数名(def)可以省略
2)案例实操
object TestFunction {
def main(args: Array[String]): Unit = {
// 0)方法标准写法
def f1( s : String ): String = {
return s + " jinlian"
}
println(f1("Hello"))
// 至简原则:能省则省
//(1) return可以省略,scala会使用方法体的最后一行代码作为返回值
def f2( s : String ): String = {
s + " jinlian"
}
println(f2("Hello"))
// 如果方法名使用return关键字,那么方法就不能使用自行推断了,需要声明返回值类型
/*
def f22(s:String)={
return "jinlian"
}
*/
//(2)返回值类型如果能够推断出来,那么可以省略
def f3( s : String ) = {
s + " jinlian"
}
println(f3("Hello"))
//(3)如果方法体只有一行代码,可以省略花括号
//def f4(s:String) = s + " jinlian"
//def f4(s:String) = "jinlian"
def f4() = " dalang"
// 如果方法无参,但是声明参数列表,那么调用时,小括号,可加可不加。
println(f4())
println(f4)
//(4)如果方法没有参数列表,那么小括号可以省略,调用时小括号必须省略
def f5 = "dalang"
// val f5 = "dalang"
println(f5)
//(5)如果方法明确声明unit,那么即使方法体中使用return关键字也不起作用
def f6(): Unit = {
//return "abc"
"dalang"
}
println(f6())
//(6)scala如果想要自动推断无返回值,可以省略等号
// 将无返回值的方法称之为过程
def f7() {
"dalang"
}
println(f7())
//(7)如果方法明确使用return关键字,那么方法返回就不能使用自行推断了,需要声明返回值类型
def f8() :String = {
return "ximenqing"
}
println(f8())
}
}
二、函数高级
1.高阶函数
1)说明
定义:参数为函数的方法/函数称为高阶函数
2)案例实操
object TestFunction {
def main(args: Array[String]): Unit = {
//高阶函数————函数作为参数
def calculator(a: Int, b: Int, operater: (Int, Int) => Int): Int = {
operater(a, b)
}
//函数————求和
def plus(x: Int, y: Int): Int = {
x + y
}
//方法————求积
def multiply(x: Int, y: Int): Int = {
x * y
}
//函数作为参数
println(calculator(2, 3, plus))
println(calculator(2, 3, multiply))
}
}
2.匿名函数
1)说明
没有名字的函数就是匿名函数,可以直接通过函数字面量(λ表达式)来设置匿名函数,函数字面量定义格式如下。
没有函数名:
匿名函数的作用:匿名函数一般用于给高阶函数传参。
(name:String) => { println(name) }
(name:String) => print(name)
省略原则:
-
参数的类型可以省略,会根据形参进行自动的推导
-
类型省略之后,发现只有一个参数,则圆括号可以省略,
其他情况:没有参数和参数超过1的永远不能省略圆括号 -
匿名函数如果只有一行,则括号可以省略
-
如果参数只出现一次,则参数省略且后面参数可以用_代替。
-
如果可以推断出,当前出入的println是一个函数体,而不是调用语句,则可以直接省略下划线
2)案例实操
object TestFunction {
//高阶函数————函数作为参数
def calculator(a: Int, b: Int, operator: (Int, Int) => Int): Int = {
operator(a, b)
}
//函数————求和
def plus(x: Int, y: Int): Int = {
x + y
}
def main(args: Array[String]): Unit = {
//函数作为参数
println(calculator(2, 3, plus))
//匿名函数作为参数
println(calculator(2, 3, (x: Int, y: Int) => x + y))
//匿名函数简写形式
println(calculator(2, 3, _ + _))
}
}
3.函数柯里化&闭包
1)说明
函数柯里化:将一个接收多个参数的函数转化成一个接受一个参数的函数过程,可以简单的理解为一种特殊的参数列表声明方式。
闭包:就是一个函数和与其相关的引用环境(变量)组合的一个整体(实体)
另一种说法:
2)案例实操
(1)闭包
//外部变量
var z: Int = 10
//闭包
def f(y: Int): Int = {
z + y
}
(2)柯里化
object TestFunction {
val sum = (x: Int, y: Int, z: Int) => x + y + z
val sum1 = (x: Int) => {
y: Int => {
z: Int => {
x + y + z
}
}
}
val sum2 = (x: Int) => (y: Int) => (z: Int) => x + y + z
def sum3(x: Int)(y: Int)(z: Int) = x + y + z
def main(args: Array[String]): Unit = {
sum(1, 2, 3)
sum1(1)(2)(3)
sum2(1)(2)(3)
sum3(1)(2)(3)
}
}
4.递归
1)说明
一个函数/方法在函数/方法体内又调用了本身,我们称之为递归调用
2)案例实操
object TestFunction {
def main(args: Array[String]): Unit = {
// 阶乘
// 递归算法
// 1) 方法调用自身
// 2) 方法必须要有跳出的逻辑
// 3) 方法调用自身时,传递的参数应该有规律
// 4) scala中的递归必须声明函数返回值类型
println(test(5))
}
def test( i : Int ) : Int = {
if ( i == 1 ) {
1
} else {
i * test(i-1)
}
}
}
5.控制抽象
Scala中可以自己定义类似于if-else,while的流程控制语句,即所谓的控制抽象。
案例:定义如下控制结构
loop(5) {
println("control")
}
上述控制结构的功能为将println("control")循环执行5次。
提示:scala中,以下结构称为代码块(block),可视为无参函数,作为 =>Unit类型的参数值。
{
code
}
实操
object TestBlock {
def loop(n: Int)(op: => Unit): Unit = {
if (n > 0) {
op
loop(n - 1)(op)
}
}
def main(args: Array[String]): Unit = {
loop(5) {
println("test")
}
}
}
6.惰性求值
1)说明
当函数返回值被声明为lazy时,函数的执行将被推迟,直到我们首次对此取值,该函数才会执行。这种函数我们称之为惰性函数。
2)案例实操
def main(args: Array[String]): Unit = {
lazy val res = sum(10, 30)
println("----------------")
println("res=" + res)
}
val sum =(n1: Int, n2: Int)=> {
println("sum被执行。。。")
return n1 + n2
}
输出结果:
----------------
sum被执行。。。
res=40
注意:lazy不能修饰var类型的变量