函数式编程
面向对象编程
分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题
函数式编程
将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用这些封装好的功能按照指定的步骤,解决问题。
基础函数编程
基本语法
[修饰符] def 函数名 ( 参数列表 ) [:返回值类型] = {
函数体
}
private def test( s : String ) : Unit = {
println(s)
}
函数&方法
- scala 中存在方法与函数两个不同的概念,二者在语义上的区别很小。scala 方法是类的一部分,而函数是一个对象,可以赋值给一个变量。换句话来说在类中定义的函数即是方法。scala 中的方法跟 Java 的类似,方法是组成类的一部分。scala 中的函数则是一个完整的对象。
- Scala中的方法和函数从语法概念上来讲,一般不好区分,所以简单的理解就是:
方法也是函数
。只不过类中声明的函数称之为方法,其他场合声明的就是函数了。类中的方法是有重载和重写的。而函数可就没有重载和重写的概念了,但是函数可以嵌套声明使用,方法就没有这个能力了,千万记得哟。
函数定义
1)无参,无返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun1(): Unit = {
println("函数体")
}
fun1()
}
}
2)无参,有返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun2(): String = {
"zhangsan"
}
println( fun2() )
}
}
3)有参,无返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun3( name:String ): Unit = {
println( name )
}
fun3("zhangsan")
}
}
4)有参,有返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun4(name:String): String = {
"Hello " + name
}
println( fun4("zhangsan") )
}
}
5)多参,无返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun5(hello:String, name:String): Unit = {
println( hello + " " + name )
}
fun5("Hello", "zhangsan")
}
}
6)多参,有返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun6(hello:String, name:String): String = {
hello + " " + name
}
println( fun6("Hello", "zhangsan"))
}
}
函数参数
1)可变参数
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun7(names:String*): Unit = {
println(names)
}
fun7()
fun7( "zhangsan" )
fun7( "zhangsan", "lisi" )
}
}
可变参数不能放置在参数列表的前面,一般放置在参数列表的最后
oobject ScalaFunction {
def main(args: Array[String]): Unit = {
// Error
//def fun77(names:String*, name:String): Unit = {
//}
def fun777( name:String, names:String* ): Unit = {
println( name )
println( names )
}
}
}
2)参数默认值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun8( name:String, password:String = "000000" ): Unit = {
println( name + "," + password )
}
fun8("zhangsan", "123123")
fun8("zhangsan")
}
}
3)带名参数
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun9( password:String = "000000", name:String ): Unit = {
println( name + "," + password )
}
fun9("123123", "zhangsan" )
fun9(name="zhangsan")
}
}
函数至简原则
所谓的至简原则,其实就是Scala的作者为了开发人员能够大幅度提高开发效率。通过编译器的动态判定功能,帮助我们将函数声明中能简化的地方全部都进行了简化。也就是说将函数声明中那些能省的地方全部都省掉。所以这里的至简原则,简单来说就是:能省则省。
1)省略return关键字
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun1(): String = {
return "zhangsan"
}
def fun11(): String = {
"zhangsan"
}
}
}
2)省略花括号
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun2(): String = "zhangsan"
}
}
3)省略返回值类型
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun3() = "zhangsan"
}
}
4)省略参数列表
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun4 = "zhangsan"
}
}
5)省略等号
如果函数体中有明确的return语句,那么返回值类型不能省略
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun5(): String = {
return "zhangsan"
}
println(fun5())
}
}
如果函数体返回值类型明确为Unit, 那么函数体中即使有return关键字也不起作用
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun5(): Unit = {
return "zhangsan"
}
println(fun5())
}
}
如果函数体返回值类型声明为Unit, 但是又想省略,那么此时就必须连同等号一起省略
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun5() {
return "zhangsan"
}
println(fun5())
}
}
6)省略名称和关键字
object ScalaFunction {
def main(args: Array[String]): Unit = {
() => {
println("zhangsan")
}
}
}
高阶函数编程
函数作为值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun1(): String = {
"zhangsan"
}
val a = fun1
val b = fun1 _
println(a)
println(b)
}
}
object Scala06_Function {
def main(args: Array[String]): Unit = {
// TODO Scala 函数式编程 - 函数作为值
def test(name:String):String ={
"name =" + name
}
def test1(): Unit ={
println("test1.....")
}
def test3(name:String,age:Int) :Unit ={
println("name = " + name +" , age = "+ age )
}
//test1
// 将函数赋值给变量
// 1. 如果希望将函数对象赋值给变量,需要通过 (函数名 _ ) 来进行赋值
val fun1 = test _
println(fun1("zhangsan"))
//2. 如果不想使用下划线将函数赋值给某个变量.
val fun2 : String => String = test
println(fun2("lisi"))
val fun3: (String,Int)=>Unit = test3
val fun4 = test3 _
}
}
函数作为参数
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun2( i:Int ): Int = {
i * 2
}
def fun22( f : Int => Int ): Int = {
f(10)
}
println(fun22(fun2))
}
}
object Scala07_Function {
def main(args: Array[String]): Unit = {
// TODO Scala 函数式编程 - 函数作为参数
// 函数是一个对象. 有具体的类型.
def test(): Unit ={
println("Hello test.....")
}
def fun(f:()=>Unit): Unit ={
f()
}
// fun(test)
def test1(name:String):String={
"name = " + name
}
def fun1(f:String=>String,name:String):String={
f(name)
}
println(fun1(test1, "zhangsan"))
}
}
函数作为返回值
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun3( i:Int ): Int = {
i * 2
}
def fun33( ) = {
fun3 _
}
println(fun33()(10))
}
}
object Scala10_Function {
def main(args: Array[String]): Unit = {
// TODO Scala 函数式编程 - 函数作为返回值
def test(name:String):String ={
"name = "+ name
}
//val b = test _
//val bb : String => String = test
def fun() ={
test _
}
def fun1():String =>String ={
test
}
// 调用
println(fun()("zhangsan"))
// TODO 2. 嵌套函数
// 外部函数
def fun2():String => String = {
// 内部函数
def test2(name:String):String={
"name = " + name
}
test2 _
}
}
}
匿名函数
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun4( f:Int => Int ): Int = {
f(10)
}
println(fun4((x:Int)=>{x * 20}))
println(fun4((x)=>{x * 20}))
println(fun4((x)=>x * 20))
println(fun4(x=>x * 20))
println(fun4(_ * 20))
}
}
object Scala08_Function {
def main(args: Array[String]): Unit = {
// TODO Scala 函数式编程 - 函数作为参数 - 匿名函数
// 函数是一个对象. 有具体的类型.
// 通常情况下, 函数作为参数使用时,都会使用匿名函数
// 至简原则:
// 1. 如果匿名函数的函数体只有一行语句,{} 可以省略
// 2. 如果匿名函数的参数的类型可以推断,参数类型可以省略.
// 3. 如果匿名函数的参数只有一个,()可以省略。
// 4. 如果匿名函数的参数在函数体中只使用一次,参数 和 =>同时省略. 使用 _ 代替参数.
def fun(f:String => String):String={
f("zhangsan")
}
def test(name :String):String={
name * 2
}
//fun(test)
println(fun((name: String) => {
println("haha")
name * 2
}
))
println(fun((name: String) => name * 2))
println(fun((name) => name * 2))
println(fun(name => name * 2))
println(fun( _ * 2))
// 实现一个计算的功能. 可能计算的功能有: + - * /
def cal(f:(Int,Int)=>Int,x:Int,y:Int):Int={
f(x,y)
}
println(cal((i: Int, j: Int) => {i + j}, 10, 20))
println(cal((i, j) => {i + j}, 10, 20))
println(cal( {_ + _} , 10, 20))
}
}
闭包
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun5() = {
val i = 20
def fun55() = {
i * 2
}
fun55 _
}
fun5()()
}
}
object Scala11_Function {
def main(args: Array[String]): Unit = {
// TODO Scala 函数式编程 - 嵌套函数 - 闭包
// 内部函数使用了外部的变量, 而外部的变量在外部函数执行完后就已经没有作用域了.
// 但是内部函数能正常使用到外部函数的外部变量, 因为编译器修改了内部函数的参数列表。
// 将外部的变量作为内部函数的参数传递到了内部的函数.
// 把这个现象就称之为闭包
// 这只是闭包的一种现象.
// 其实闭包还有别的表现: 匿名函数就是闭包现象 将函数作为值赋值给变量也是闭包想象 嵌套函数中内部函数在外部使用也是闭包现象.
// 当前的版本(2.12) :
// 早期的版本(2.11) : 如果有闭包现象,编译后会多出一个匿名类。
// Spark : Spark如何判断是否闭包现象
def fun1(i:Int):Int=>Int ={
def fun2(j:Int):Int={
i + j
}
fun2 _
}
println(fun1(1)(2)) // 调用完fun1()拿到返回值后 -> 调用fun2()
// TODO 匿名函数
/*
def test(f:String => String):Unit={
println(f("zhangsan"))
}
test(_ * 2 )
*/
// TODO 将函数赋值给变量
/*
def test(): Unit ={
}
val b = test _
*/
// TODO 嵌套函数的内部函数在外部使用
/*
def test(): ()=>Unit ={
def test1(): Unit ={
}
test1 _
}
*/
}
}
函数柯里化
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun6(i:Int)(j:Int) = {
i * j
}
}
}
object Scala12_Function {
def main(args: Array[String]): Unit = {
// TODO Scala 函数式编程 - 柯里化
// 所谓的函数柯里化,实际上就是支持写多个参数列表
// 也有一个好处就是能够简化复杂的参数列表
def test (i:Int ): Unit ={
def test1(j:Int): Unit ={
println(i + j )
}
test1(10)
}
test(20)
def fun(i:Int,m:Int)(j:Int): Unit ={
println(i + j )
}
def fun1(i:Int)(j:Int)(f:(Int,Int)=>Int): Int ={
f(i,j)
}
println(fun1(1)(2)(_ + _))
}
}
控制抽象
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun7(op: => Unit) = {
op
}
fun7{
println("xx")
}
}
}
object Scala13_Function {
def main(args: Array[String]): Unit = {
// TODO Scala 函数式编程 - 控制抽象
// 从1 循环到 5 ,当循环到3的时候,跳出循环
Breaks.breakable{
for(i <- 1 to 5 ){
if(i == 3){
Breaks.break()
}
println("i = " + i)
}
}
println("xxxxxxxx")
def my(op: =>String){
println("my 开始......")
println(op)
println("my 结束......")
}
// my(println(123))
my{
val age =20
if(age < 20){
//println("少年")
"少年"
}else{
//println("打工者...")
"打工的"
}
}
}
}
递归函数
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun8(j:Int):Int = {
if ( j <= 1 ) {
1
} else {
j * fun8(j-1)
}
}
println(fun8(5))
}
}
object Scala14_Function {
def main(args: Array[String]): Unit = {
// TODO Scala 函数式编程 - 递归函数
// 递归: 自己调用自己
// 注意: 1. 递归一定要有退出的条件
// 2. 在scala中递归的方法需要明确声明返回值类型
// 例子: 5 + 4 + 3 + 2 + 1
/*
// 发散性递归
def sum(num:Int):Int={
if(num <=1){
1
}else{
num + sum(num - 1 )
}
}
// println(sum(5))
println(sum(1000000000)) //java.lang.StackOverflowError
*/
def fun(): Unit ={
println()
fun()
}
// 尾递归
// 5 , 0 => sum(4, 5)
// 4 , 5 => sum(3, 9 = 5 + 4 )
// 3 , 9 => sum(2,12 = 5 + 4 + 3 )
// 2 ,12 => sum(1,14 = 5 + 4 + 3 + 2 )
// 1 ,14 => sum(0,15 = 5 + 4 + 3 + 2 + 1)
// 0 ,15 => 15
def sum(num:Int,result:Int):Int={
if(num < 1 ){
result
}else{
sum(num-1, num + result )
}
}
println(sum(100000000, 0))
}
}
惰性函数
当函数返回值被声明为lazy时,函数的执行将被推迟,直到我们首次对此取值,该函数才会执行。这种函数我们称之为惰性函数。
object ScalaFunction {
def main(args: Array[String]): Unit = {
def fun9(): String = {
println("function...")
"zhangsan"
}
lazy val a = fun9()
println("----------")
println(a)
}
}
object Scala15_Function {
def main(args: Array[String]): Unit = {
// TODO Scala 函数式编程 - 惰性函数 lazy
def test ():String={
println("test......")
"zhangsan"
}
lazy val username = test()
println("xxxxxxxxxxxxxxxxxxxxxxxxxx")
println("username :" + username)
}
}