Scala方法與函數使用和定義詳解
一、方法的定義
1.方法體中最後返回值可以使用return, 如果使用瞭return, 那麼方法體的返回值類型一定要指定
2.如果方法體重沒有return, 默認將 方法體中最後一行計算的結果當作返回值返回. 方法體的返回值可以省略, 會自動推斷
3.定義方法傳入的參數一定要指定類型
4.方法的方法體如果隻有一行, 那麼方法體的“{…}”可以省略
5.如果定義方法時, 省略瞭方法名稱和方法體之間的"=", 那麼無論方法體最後一行計算的結果是什麼, 都會被丟棄, 返回Unit
def max(a: Int, b: Int) = { if (a > b) { "哈哈" } else { b } } // 語法糖: 方法定義 def max0(a: Int, b: Int) = if (a > b) a else b
註:記住def定義的格式,按著格式敲即可,不要糾結
二、遞歸方法
遞歸方法必須要顯示指定返回體的類型
def fun2(num: Int): Int = { if (num == 1) num else num * fun2(num - 1) } // 語法糖 def fun2(num:Int) : Int = if (num == 1) num else num * fun2(num - 1)
註:編譯器無法直接推斷出你最終遞歸的結果類型,所以需要你顯示指定
三、參數有默認值的方法
1.默認值的函數中,如果傳入的參數個數與函數定義相同,則傳入的數值會覆蓋默認值
2.如果不想覆蓋默認值,傳入的參數個數小於定義的函數的參數,則需要指定參數名稱
def fun3(a: Int = 10, b: Int) = { println(a + b) }
四、可變參數個數的函數
多個參數之間逗號分開
def fun4(elements: Int*) = { println(elements) elements.foreach(i => println(i)) // 當匿名函數的元素隻用到一次的時候, 可以用_簡寫 elements.foreach(println(_)) // 當方法入參為單個參數時且正好是匿名函數的元素時, 進一步簡寫 elements.foreach(println) var sum = 0; for (elem <- elements) { sum += elem } sum }
五、匿名函數
註意函數的寫法與方法的寫法有些許的不同,出現 => 符號就認為是函數,但實際使用上效果並無不同,僅僅是語法上的細微區別
原生的匿名函數寫法(基本不用):(Int, Int) => Int就是他的類型
/** * 原生的匿名函數寫法(基本不用) * @return */ def fun: (Int, Int) => Int = (a: Int, b: Int) => { a + b }
常用的匿名函數寫法: 可以將匿名函數返回給定義的一個變量, 看到“=>”就是匿名函數, 多用於方法的參數是函數時(函數指針),用匿名函數簡寫
/** * 常用的匿名函數寫法: 可以將匿名函數返回給定義的一個變量, 看到“=>”就是匿名函數 * 多用於方法的參數是函數時(函數指針),用匿名函數簡寫 * * @param args */ def main(args: Array[String]): Unit = { /** * 有參數匿名函數 */ val value1: (Int) => Unit = (a: Int) => { println(a) } value1(1) /** * 無參數匿名函數 */ val value2 = () => { println("我愛學習") } value2() /** * 有返回值的匿名函數 */ val value3 = (a: Int, b: Int) => { a + b } println(value3(4, 4)) }
六、嵌套方法
/** * 嵌套方法 * 例如:嵌套方法求5的階乘 */ def fun5(num: Int) = { def fun6(a: Int, b: Int): Int = { if (a == 1) { b } else { fun6(a - 1, a * b) } } fun6(num, 1) }
七、偏應用函數(部分應用函數)
某些情況下, 方法中參數非常多, 調用這個方法非常頻繁, 每次調用隻有固定的某個參數變化, 其他都不變, 可以定義偏應用來實現
def showLog(date :Date, log :String)= { println(s"date is $date, log is $log") } def main(args: Array[String]): Unit = { val date = DateUtil.date(new Date()) showLog(date,"當前時間") // 想要調用log, 以上變化的是第二個參數, 可以用偏應用函數處理 // 把showLog()方法定義為偏應用函數 val logWithDate = showLog(date,_:String) // 第二種函數寫法 def logWithDate2 = showLog(date,_:String) logWithDate("偏應用函數-log11") logWithDate("偏應用函數-log22") logWithDate("偏應用函數-log33") }
八、高階函數
函數的參數是函數,或者函數的返回類型是函數,或者函數的參數和函數的返回類型是函數的函數.
/** * 普通的方法 * * @param a * @param b * @return */ def fun(a: Int, b: Int): Int = { a + b } /** * 使用 _把方法強轉為一個函數 */ private val function: (Int, Int) => Int = fun _ /** * 函數的參數是函數: 函數的類型 (Int, Int) => Int, 記住: 方法的引用僅為方法本身,需要重新賦實參 * * @param f 函數作為參數 * @param a * @return */ def fun1(f: (Int, Int) => Int, a: Int): Int = { f(a, 100) } /** * 函數的返回是函數: 必須要顯示地寫出返回值類型, 或者使用 f2 _ * * @param a * @param b * @return */ def fun2(a: Int, b: Int): (Int, Int) => Int = { // 在內部定義瞭一個方法 def f2(v1: Int, v2: Int): Int = { v1 + v2 + a + b } f2 } /** * 函數的參數是函數,函數的返回是函數 * * @param f * @return */ def fum3(f: (Int, Int) => Int): (String, String) => String = { val i = f(1, 2) def fun1(s1: String, s2: String): String = { s1 + "@" + s2 + "$" + i } fun1 } /** * 函數入口 * * @param args */ def main(args: Array[String]): Unit = { // 顯示聲明過的函數作為參數 println("顯示聲明過的函數作為參數: " + fun1(fun, 100)) // 匿名函數作為參數: 匿名函數入參的類型可以省略不寫 println("匿名函數作為參數: " + fun1((a: Int, b: Int) => { a * b }, 100)) // 返回值是一個函數 println("返回值是一個函數: " + fun2(1, 2)(3, 4)) // 入參和出參都是函數 println("入參和出參都是函數: " + fum3(fun)("hello", "scala!")) println("入參和出參都是函數: " + fum3((a, b) => a * b)("hello", "scala!")) }
筆者註:高階函數這塊內容會相對較為難以理解,可以先記住這種結構
九、柯裡化函數
柯裡化函數: 本質上就是對返回值是函數的方法的一種簡化寫法
def fun7(a: Int, b: Int)(c: Int, d: Int) = { a + b + c + d } /** * 函數入口 * * @param args */ def main(args: Array[String]): Unit = { println(fun7(1, 2)(3, 4)) }
註:fun7(1, 2)(3, 4)可以理解成先運算fun7(1,2)返回瞭一個fun7函數對象,再對他進行參數(3,4)的賦值
到此這篇關於Scala方法與函數使用和定義詳解的文章就介紹到這瞭,更多相關Scala方法與函數內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- java與scala數組及集合的基本操作對比
- Scala中Array和List的區別說明
- python Scala函數與訪問修辭符實例詳解
- Java Scala數據類型與變量常量及類和對象超詳細講解
- Java與Scala創建List與Map的實現方式