1. 程式人生 > >Scala系列5、Scala中的函式

Scala系列5、Scala中的函式

1、方法中的return是可以預設的,scala會將函式的最後一句作為返回值;   方法還可以預設返回值型別,scala會自動進行型別推斷,但是如果是遞迴函式就必須指定返回這型別。但是最好還是不要省略返回值型別2、scala中的引數和Java中的引數不太一樣。Java引數有形參和實參的區別,但在scala中有時形參和實參是一致的。參看【scala指定函式引數名】3、=>左側表示輸入,右側表示轉換操作4、scala函式中的引數都是val的,所以不能在函式體內再次給引數賦值    5、Scala定義函式的方法6、函式的傳值呼叫和傳名呼叫:傳值呼叫就是普通意義上的呼叫;著重說下傳名呼叫。其語法是: def addByName(a: => Int) = a 比傳值呼叫多了一個=>,傳名呼叫只有在函式體中實際呼叫時才會計算表示式的值,只是兩個呼叫方式的最大區別。
     Scala除了支援面向物件之外,還是一門函式式語言,因此函式是Scala的核心。    定義函式,需要給出函式的名字、引數和函式體:def method(x: Int) = if(x>0) x else -x    函式需要給出所有引數的型別。只要函式不遞迴是可以不寫return,scala可以根據=右邊的式子推匯出函式的返回值型別。    函式要定義在object中,紅框中的叫函式宣告。如果不寫等號和方法體,則方法會被隱式的宣告為“抽象abstract”。對於函式的呼叫,跟Java的方式一樣。使用對應的函式名,如果有引數,傳入對應的引數即可呼叫。    如果函式體需要多個表示式來完成需求,可是使用程式碼塊。程式碼塊中的最後一句就是函式的返回值。如下例:如果要使用return返回 a+b的值,則必選要標明函式的返回型別
【過程】    scala對於不返回值的函式有特使的表示方法:如果函式體包含在花括號中但是沒有前面的=,那麼返回型別就是Unit,這樣的函式就叫做過程。過程不返回值,呼叫過程是為了使用它的副作用。如:我們需要列印一些圖案,那麼就可以定義如下過程:def main(args: Array[String]): Unit = {draw("123")}//draw(s:String){}  對於沒有返回這的過程,這種寫法也是對的def draw(s: String): Unit ={println("-----")println("|"+" "+"|")println("|"+s+"|")println
("|"+" "+"|")
println("-----")}【預設引數值】    在scala函式中,可以為函式的引數指定預設值。當我們呼叫這個函式沒有給引數傳值的時候,就會啟用預設引數值。如果指定了引數值,就會使用指定的引數值。    在下面這個例子中的第三個輸出語句中,我們還可以不按照引數順序來傳值,但是需要在傳值的時候指定引數名object HelloWorld {def main(args: Array[String]): Unit = {println(outputBook("book1"));println(outputBook("book2","[","]"));println(outputBook(right="***]",bookname = "book3"))}def outputBook(bookname: String,left:String="{",right:String="}") = left + bookname + right;}//執行結果{book1}[book2]{book3***]【可變引數】    scala支援可變引數,實現方式與Java稍有不同。scala的變長引數是用 * 宣告。本例中,如果想要實現一個序列作為引數傳入,需要追加 _*,意思就是告訴編譯器把這個引數當做引數序列處理。    直接傳入一個序列使錯誤的,因為這這個例子中,傳入的引數被限制為單個引數,所以直接傳入一個整數區間是不被接受的。解決辦法就是在序列後面追加 _*,來告訴編譯器我們希望這個引數被當做單數序列處理。def main(args: Array[String]): Unit = {println(sum(1,2,3,4,5))//序列作為引數println(sum(1 to 5: _*))}//變長引數def sum(args: Int*): Int ={var res = 0for(n <- args){res += n;}return res;}///////////////////////////【Scala指定函式引數名】    通常情況下,我們想呼叫一個引數都是按照函式定義的引數順序一個個傳遞。在scala中我們也可以通過指定函式的引數名,而不一定需要按照函式定義的引數順序向函式傳遞引數。def main(args: Array[String]): Unit = {printInt(b=5, a=8);}def printInt(a: Int, b: Int): Unit = {println(a);println(b);【Scala函式的呼叫】    1、傳值呼叫,這種方式就是Java中最常見的函式呼叫方式。def main(args: Array[String]): Unit = {    var increase = (x: Int) => x+1    println(increase(10))    println("2:"+increase2(13))}//相當於這種形式  這種寫法是極簡寫法,省略了返回型別、返回值和方法體的括號def increase2(x: Int) = x+1;//如果是多個語句的情況val increaseAnother = (x: Int) =>{    println("多條語句")    println("請使用\"{}\"")    x + 1}println(increaseAnother(12))    2、傳名呼叫,將未計算的表示式傳進函式。傳名呼叫的語法是:在使用傳名呼叫時,在引數名稱和引數型別之間有一個"=>"符號。傳名呼叫是在函式內部進行表示式值計算的。而傳值呼叫在傳入函式內部之前就已經把引數表示式的值計算完畢。    示例程式碼如下:    =>左側表示輸入,右側表示轉換操作def main(args: Array[String]): Unit = {    //函式的傳名呼叫    delayed(time())}def time() ={    println("time方法,獲取時間")    System.nanoTime()}def delayed(t: => Long) = {    println("delayed方法中呼叫time方法"); //在真正呼叫引數t的時候才會開始計算t的值    println("引數t:"+t); //又呼叫了一次time()來計算t的值    t}    在main方法中我們呼叫了delayed方法,傳的引數是time()。delayed方法通過 =>符號來設定傳名呼叫。     執行結果:    在執行的時候,首先進入delayed方法。接著delayed方法列印了接收到的值,這一步就在delayed內部執行了time方法。最後再次通過引數t呼叫了time()方法。
【匿名函式】    scala中定義匿名函式的語法很簡單。箭頭左邊是引數列表,右邊是函式體def main(args: Array[String]): Unit = {//定義一個匿名函式var inc = (x: Int) => x+1;    println(inc(20))}