1、面向对象编程和函数式编程
2、函数定义格式
def 函数名 ([参数名: 参数类型], ...)[[: 返回值类型] =] {
语句... //完成某个功能
return 返回值
}
def test(s:String) : String ={
return "abc"
}
3、函数的各种简化和变形
1) 省略return (方法体内最后一行为返回的值)
def test1(s:String) : String ={
"abc"
}
println(test1("a")) // abc
2) 省略返回值类型(scala会自动判断最后一行值的类型)
def test2(s:String) ={
"abc"
}
println(test2("a")) // abc
3) 省略入参
def test3() ={
"abc"
}
println(test3()) // abc
4)省略大括号()当方法体内只有一行代码时,可以省略{ }
def test4() ="abc"
println(test4()) // abc
5)省略小括号 当方法没有入参时,可以省略()
def test5 = "abc"
println(test5) // abc 若方法省了小括号,在调用时也可以省略小括号
def test5 = "abc"
val ssss = "abc"
方法和变量只有关键字不一样
6)补充
- 方法省略等号,返回值为Unit
def test6(){
"abc"
}
println(test6()) // ()
- 方法体没有返回值是Unit,
只要定义的返回值时Unit,不管方法体最后一行是什么都会返回Unit
//方法体没有返回值是Unit,
// 要定义的返回值时Unit,不管方法体最后一行是什么都会返回Unit类型
def test1(s:String) : Unit ={
}
def test2(s:String) : Unit ={
"abc"
}
println(test1("a")) // ()
println(test2("a")) // ()
- 7)可变参
def test7(s:String*)={
for(i<- s){
println(i)
}
}
test7("张三","里斯") //张三
//里斯
4、Scala是完全面向函数的语言
注意:
函数的类型:() => Int、Int => Int 、(Int) = >Int等
1)函数可以赋值给变量
2)函数可以作为函数的参数
def f5(f6 : () => Int): Int ={
f6()+10
}
def f(): Int ={
5
}
println(f5(f)) //15
简化(匿名函数)
def f5(f6 : () => Int): Int ={
f6()+10
}
println(f5(()=>{5})) //15
val a = ()=>{"a"}
println(a) // <function0>
println(a()) // a
匿名函数加强(匿名函数传递的是一段逻辑)
def f7(f : (Int) => Unit) : Unit = {
f(10)
}
f7((i) => {println(i)}) //10
f7((i) => println(i)) //10
f7(i => println(i)) //10
f7(println(_)) //10
def f8(f:(Int,Int) => Int): Int = {
f(10,10)
}
println(f8((x:Int,y:Int) => {x+y})) // 20
println(f8((x,y) => { x+y })) // 20
println(f8((x,y) => x+y)) // 20
println(f8(_+_)) // 20
3)函数可以作为函数的返回值
def f()={
"scala"
}
def f1() ={
f //当方法没有入参时,调用时可以省略小括号
}
println(f1()) // scala
println(f1()()) // 直接提示错误
def f()={
"scala"
}
def f1() ={
f _ // 有 _ 返回才是函数,而不是值
}
println(f1()) // <function0>
println(f1()()) // scala
解释:一般情况下,f标识传递引用,f()表示实际调用
f _ :中的 _ 如果不写返回值并不是一个函数,而是f函数的返回值。在函数f1中,函数f也会执行(因为无参函数调用,可以省略小括号)。
简化
def f1():() => String ={
def f() : String ={
"scala"
}
f _ //scala中函数哪里都写可以,这种只是相当于把f函数写道f1里面
}
print(f1()())
解释:
()=>String 代表返回的是一个函数,没有入参,返回值是String的函数
再变型
def f2(i :Int) : Int => Int ={
def f3(j:Int): Int ={
i*j
}
f3 _
}
println(f2(3)(4)) //12
注意:正常再触发f3函数时,f2已经弹栈,入参i不能再f3中拿到运用,这里有个闭包的概念。把i 的生命周期改变,就像再把i和j打成一个包,放到f3里面
关于闭包的类比:
类似java堆栈,通常认知,方法进栈,对象进堆
1、栈上分配
public void test(){
User user = new User
//如果创建千万对象,弹栈后,方法之外的地方也没有用到这些对象,则这些对象随着方法弹栈,不进入堆中
}
2、逃逸分析
public User test(){
User user = new User
return user
// 方法返回了对象,这时不在随方法弹栈,逃逸进入堆中
}
柯里化(上面的简化)
def f2(i:Int)(j:Int) : Int = {
i*j
}
println(f2(3)(4))
5、其他知识点
- 惰性函数
def sum(i:Int,j:Int): Int ={
println("sum函数执行了")
i+j
}
val res = sum(10,20)
println("----------x----------")
println("----------x----------")
println("----------x----------")
println(res)
结果:sum函数执行了
----------x----------
----------x----------
----------x----------
30
lazy val res = sum(10,20)
println("*******x********")
println("*******x********")
println("*******x********")
println(res)
结果:
*******x********
*******x********
*******x********
sum函数执行了
30
- 惰性函数加载时才执行
- lazy不能修饰var变量
- lazy修饰函数和变量,都会导致延迟加载