scala(五) 函數(shù)式編程

  1. 面向對象編程
    解決問題趟据,分解對象,行為术健,屬性汹碱,然后通過對象的關系以及行為的調用來解決問題。
    對象:用戶荞估;
    行為:登錄咳促、連接jdbc稚新、讀取數(shù)據(jù)庫
    屬性:用戶名、密碼
    Scala語言是一個完全面向對象編程語言等缀。萬物皆對象
  2. 函數(shù)式編程
    解決問題時枷莉,將問題分解成一個一個的步驟,將每個步驟進行封裝(函數(shù))尺迂,通過調用這些封裝好的步驟笤妙,解決問題。
    例如:請求->用戶名噪裕、密碼->連接jdbc->讀取數(shù)據(jù)庫
    Scala語言是一個完全函數(shù)式編程語言蹲盘。萬物皆函數(shù)
  3. 在Scala中函數(shù)式編程和面向對象編程融合在一起了。

方法基本語法

語法:


scala語法

說明:

  1. def : 關鍵字膳音,表示聲明方法
  2. add:方法名召衔,根據(jù)業(yè)務進行取名
  3. 參數(shù)名稱在前 : 參數(shù)類型在后,多個參數(shù)用 , 分割
  4. 返回類型:若無返回類型 可定義為 Unit 或 無需定義
  5. 函數(shù)體:用于編寫的業(yè)務邏輯的語句塊

與java方法的區(qū)別:

  1. scala 可以將函數(shù)定義到任意位置祭陷,甚至在一個函數(shù)內(nèi)定義一個函數(shù)苍凛。
def main(args: Array[String]): Unit = {
    def sayHello(){
      print("hello")
    }
    sayHello // hello
}
  1. java 只能將方法定義在類中,不能定義在另一個方法中

方法的定義:

  1. 函數(shù)1:無參兵志,無返回值
  def sayHello(){
      print("hello")
  }
  1. 函數(shù)2:無產(chǎn)醇蝴,有返回值
  def main(args: Array[String]): Unit = {
    
    println(sayHello) // hello
  }

  def sayHello():String={
      "hello"
  }
  1. 函數(shù)3:有參,無返回值
  def main(args: Array[String]): Unit = {
    
    sayHello("張三")
  }

  def sayHello(name:String){
      println(s"你好想罕,$name 童鞋") // 你好悠栓,張三 童鞋
  }

  1. 函數(shù)4:有參,有返回值
  def main(args: Array[String]): Unit = {
    
    println(sum(10,20)) // 30
  }

  def sum(x:Int,y:Int):Int={
     x+y
  }
  1. 函數(shù)5:多參按价,無返回值
  def main(args: Array[String]): Unit = {
    
    sum(10,20) // 30
  }

  def sum(x:Int,y:Int){
     println(x+y) //30
  }
  1. 在scala中函數(shù)可以不用加 return 用來標識返回值惭适,在scala中會以最后一個參數(shù)或表達式的結果作為返回值。

方法參數(shù)

可變參數(shù)
無論是 scala 還是 java 他們都支持 可變參數(shù)
java :使用 ... 來表示
scala:使用 * 來表示
案例:

  def main(args: Array[String]): Unit = {
    info("坤坤","唱","跳","Rap","籃球")
  }

  def info(name:String,hobby:String*):Unit={
     println(s"我叫$name,我的愛好有${hobby.toList}") // 我叫坤坤,我的愛好有List(唱, 跳, Rap, 籃球)
  }

可變參數(shù)底層實現(xiàn)都是一個數(shù)組或集合楼镐,所以直接遍歷可變參癞志。

 def info(name:String,hobby:String*):Unit={
    for (h <- hobby){
      println(h)
    }
}
唱
跳
Rap
籃球

使用 可變參數(shù)需要注意:

  1. 被定義成可變參數(shù)的參數(shù),需要放在參數(shù)列表最后鸠蚪。
  2. 一個方法中只能有一個可變參數(shù)今阳。
  3. 可變參數(shù)不能與帶名參數(shù)一起使用(后面會講)

帶參默認值
在程序開發(fā)中,往往有這樣的需求茅信,當某些值為null或0時盾舌,我們需要判斷,然后給它指定一個默認值蘸鲸。
如:不指定性別妖谴,就會使用默認的性別 'M'

  def main(args: Array[String]){
    info("坤坤",60)
  }

  def info(name:String,age:Int,sex:Char='M'){
    println(s"姓名:$name,年齡:$age,性別:$sex") // 姓名:坤坤,年齡:60,性別:M
  }

我們手動指定一個性別 'F'

  def main(args: Array[String]){
    info("坤坤",60,'F')
  }

  def info(name:String,age:Int,sex:Char='M'){
    println(s"姓名:$name,年齡:$age,性別:$sex") // 姓名:坤坤,年齡:60,性別:F
  }

至于語法:以這樣的形式sex:Char='M'定義的參數(shù),就是表示給參數(shù)一個默認值。

常見錯誤寫法:

  • sex='M' :Char:我有時候也不會搞錯膝舅,直到運行報錯才反應過來嗡载。
  • sex='M':這種形式的寫法也是錯誤的,必須指定類型仍稀。

帶名參數(shù)
以上面的案例說明洼滚;第一個參數(shù)為姓名,第二個參數(shù)為年齡技潘,第三個參數(shù)為性別遥巴,一般情況下函數(shù)調用參數(shù),就按照函數(shù)定義時的參數(shù)順序一個個傳遞享幽。但是我們也可以通過指定函數(shù)參數(shù)名铲掐,并且不需要按照順序向函數(shù)傳遞參。

info(age=60,sex='F',name="坤坤")

  def main(args: Array[String]){
    info(age=60,sex='F',name="坤坤")
  }
  def info(name:String,age:Int,sex:Char='M'){
    println(s"姓名:$name,年齡:$age,性別:$sex")
  }
}
姓名:坤坤,年齡:60,性別:F

方法至簡原則(\color{red}{重點}

  1. return 可以省略值桩,scala 會使用函數(shù)體的最后一行代碼作為返回值
def main(args: Array[String]): Unit = {
    def say(context:String):String = {
      context
    }
    print(say("hello")) // hello
  }
  1. 如果函數(shù)體只有一行代碼摆霉,可以省略花括號
def main(args: Array[String]): Unit = {
    def say(context:String):String = context
    print(say("hello")) //hello
}
  1. 返回值類型如果能夠推斷出來,那么可以省略(:和返回值類型一起省略)
def main(args: Array[String]): Unit = {
    def say(context:String)= context
    print(say("hello")) // hello
}
  1. 如果有 return奔坟,則不能省略返回值類型携栋,必須指定。
def main(args: Array[String]): Unit = {
    def say(context:String):String = return context
    print(say("hello")) //hello
}
  1. 如果函數(shù)明確聲明 unit咳秉,那么即使函數(shù)體中使用 return 關鍵字也不起作用
def main(args: Array[String]): Unit = {
    def say(context:String):Unit = return context
    print(say("hello")) // ()
}
  1. scala 如果期望時無返回值類型刻两,可以省略等號
def main(args: Array[String]): Unit = {
    def say(context:String) { print(context)}
    say("hello") // hello
}

7.如果參數(shù)無參,但是聲明了參數(shù)列表滴某,那么調用時,小括號滋迈,可以不加霎奢。

def sayHello{print("hello")}
sayHello
  1. 如果函數(shù)沒有參數(shù)列表,那么小括號可以省略饼灿,調用時小括號必須省略
定義函數(shù):def sayHello{print("hello")}
掉用函數(shù):必須省略小括號 sayHello
  1. 如果不關心名稱幕侠,只關心邏輯處理,那么函數(shù)名稱(def)可以省略碍彭。這種聲明方式叫做 匿名函數(shù)(lambda 表達式)晤硕。
()=>{print("hello")}

總結:雖然很多簡化原則,但是不用去記庇忌,多敲就完了(我也記不住舞箍,沒事的時候,回顧一下筆記皆疹,知道個大概就行了疏橄。


函數(shù)的定義

語法
val 函數(shù)名 =(參數(shù)名:類型,...) => {函數(shù)體}

    // 計算兩個數(shù)的和
    val sum=(x:Int,y:Int)=>{
      x+y
    }

    println(sum(2,3)) // 5
  1. 并不需要寫返回值,函數(shù)的返回值就是塊表達式最終返回代碼結果。
  2. 調用函數(shù)和調用方法是一樣的捎迫。

函數(shù)的簡化

  1. return 可以省略晃酒,scala 會使用函數(shù)體的最后一行代碼作為返回值
val sum=(x:Int,y:Int)=>{
    x+y
}
  1. 如果函數(shù)體只有一行代碼,可以省略花括號
// 計算兩個數(shù)的和
val sum=(x:Int,y:Int)=> x+y
println(sum(2,3)) // 5
  1. 返回值類型如果能夠推斷出來窄绒,那么可以省略(:和返回值類型一起省略)
// 計算兩個數(shù)的和
val sum=(x:Int,y:Int)=> x+y
println(sum(2,3)) // 5
  1. 如果有 return贝次,則不能省略返回值類型,必須指定彰导。
函數(shù)中無法指定返回值蛔翅,至少我試了好幾次沒成功
  1. 如果函數(shù)明確聲明 unit,那么即使函數(shù)體中使用 return 關鍵字也不起作用
上面的都不行螺戳,這個也自然沒用了
  1. scala 如果期望時無返回值類型搁宾,可以省略等號
沒有等號,哈哈哈
  1. 如果參數(shù)無參倔幼,但是聲明了參數(shù)列表盖腿,那么調用時,小括號损同,可以不加翩腐。
    val sayHello=()=>{
      println("hello")
    }

不行,無法調用膏燃;函數(shù)就是一個對象茂卦,sayHello 這是這個函數(shù)的引用,并不是調用组哩。

sayHello 

打印一下該引用等龙,輸入的其實就內(nèi)存地址。

println(sayHello) // Demo02$$$Lambda$1/764977973@1fbc7afb

正確寫法

    sayHello()

函數(shù)與方法的區(qū)別

官方函數(shù)的定義

  1. 函數(shù)的定義:(x: Int) => x + 1
  2. 方法的定義:def add(x: Int, y: Int): Int = x + y println(add(1, 2)) // 3

函數(shù)與方法概念

  1. 方法就是函數(shù)伶贰,函數(shù)就是一個對象
scala> val sum=(x:Int,y:Int)=>{x+y}
sum: (Int, Int) => Int = $$Lambda$1032/841090268@778a1250 

$$Lambda$1032/841090268@778a1250  就是 sum 函數(shù)的內(nèi)存地址蛛砰。

方法存在方法區(qū),對象存在堆內(nèi)存中黍衙。

  1. 函數(shù)調用必須帶上()泥畅,否則無法調用
  2. 方法寫在類中,方法是可以被重載琅翻,函數(shù)無法被重載
    方法:
  def main(args:Array[String]):Unit={
    println(sum(1, 2)) // 3
    println(sum(1, 2,4)) // 7
  }

  def sum(x:Int,y:Int):Int={
    x+y
  }
  def sum(x:Int,y:Int,z:Int):Int={
    x+y+z
  }

但是在方法中不能重載

  def main(args:Array[String]):Unit={
    def sum(x:Int,y:Int):Int={
      x+y
    }
    def sum(x:Int,y:Int,z:Int):Int={
      x+y+z
    }

    println(sum(1, 2))
    println(sum(1, 2,4))
    
  }
Error:(7, 9) method sum is defined twice;
  the conflicting method sum was defined at line 4:9
    def sum(x:Int,y:Int,z:Int):Int={

對于函數(shù)位仁,無論是在類中,還在方法中方椎,都是不行的聂抢,因為函數(shù)需要定義變量名;變量名不能重復辩尊。

 val sum=(x:Int,y:Int)
 val sum=(x:Int,y:Int,z:Int)
  1. 方法轉函數(shù):方法名 _
  def main(args:Array[String]):Unit={

    val a=sum _
    println(a(1,2,3))

  }
  
  def sum(x:Int,y:Int,z:Int):Int={
    x+y+z
  }

函數(shù)的另一種寫法

FunctionNumNum 表示0-22個數(shù)字涛浙。最多只有23種
Function0:表示0個參數(shù)
Function1:表示1個參數(shù)
Function10:表示10個參數(shù)
Function22:表示22個參數(shù)

依舊拿 sum為例

val sum=(x:Int,y:Int)=>{
   x+y
}

它有兩個參數(shù);所以使用 Function2

    val sum2=new Function2[Int,Int,Int] {
      override def apply(v1: Int, v2: Int) = v1+v2
    }

Function2[Int,Int,Int] :
第一個Int:表示第一個參數(shù)的類型
第二個Int:表示第二個參數(shù)的類型
第三個Int:表示返回值的類型

需要重寫它的 apply 方法;在內(nèi)部做運行

override def apply(v1: Int, v2: Int)

如果代碼很多轿亮,是可以指定{}將代碼包起來

override def apply(v1: Int, v2: Int) = {
   v1+v2
}

對比一下原來的形式

    // 計算兩個數(shù)的和
    val sum1=(x:Int,y:Int)=>{x+y}

    //  Function* 的形式
    val sum2=new Function2[Int,Int,Int] {
      override def apply(v1: Int, v2: Int) = {
        v1+v2
      }
    }

調用

    println(s"sum1=${sum1(2,3)}") // 5
    println(s"sum2=${sum2(4,5)}") // 9

結語:

對于scala目前處于學習階段疮薇,以上內(nèi)容都是我學習的總結,至于內(nèi)容質量我注,仁者見仁按咒,不好的大家提出來,相互進步但骨,能幫助你的励七,我也很高興。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末奔缠,一起剝皮案震驚了整個濱河市掠抬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌校哎,老刑警劉巖两波,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異闷哆,居然都是意外死亡腰奋,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門抱怔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來劣坊,“玉大人,你說我怎么就攤上這事屈留【直” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵灌危,是天一觀的道長锐想。 經(jīng)常有香客問我,道長乍狐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任固逗,我火速辦了婚禮浅蚪,結果婚禮上,老公的妹妹穿的比我還像新娘烫罩。我一直安慰自己惜傲,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布贝攒。 她就那樣靜靜地躺著盗誊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哈踱,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天荒适,我揣著相機與錄音,去河邊找鬼开镣。 笑死刀诬,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的邪财。 我是一名探鬼主播陕壹,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼树埠!你這毒婦竟也來了糠馆?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤怎憋,失蹤者是張志新(化名)和其女友劉穎又碌,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盛霎,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡赠橙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了愤炸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片期揪。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖规个,靈堂內(nèi)的尸體忽然破棺而出凤薛,到底是詐尸還是另有隱情,我是刑警寧澤诞仓,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布缤苫,位于F島的核電站,受9級特大地震影響墅拭,放射性物質發(fā)生泄漏活玲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一谍婉、第九天 我趴在偏房一處隱蔽的房頂上張望舒憾。 院中可真熱鬧,春花似錦穗熬、人聲如沸镀迂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽探遵。三九已至窟赏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間箱季,已是汗流浹背涯穷。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留规哪,地道東北人求豫。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像诉稍,于是被迫代替她去往敵國和親蝠嘉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容