成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Scala方法和函數(shù)的區(qū)別是什么

這期內(nèi)容當中小編將會給大家?guī)碛嘘PScala 方法和函數(shù)的區(qū)別是什么,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

成都創(chuàng)新互聯(lián)公司是一家以成都網(wǎng)站建設公司、網(wǎng)頁設計、品牌設計、軟件運維、營銷推廣、小程序App開發(fā)等移動開發(fā)為一體互聯(lián)網(wǎng)公司。已累計為成都服務器托管等眾行業(yè)中小客戶提供優(yōu)質的互聯(lián)網(wǎng)建站和軟件開發(fā)服務。

Scala中既有函數(shù)(Function)也有方法(Method),大多數(shù)情況下我們都可以不去理會他們之間的區(qū)別。但是有時候我們必須要了解他們之間的不同。

Scala 中的方法跟 Java 的方法一樣,方法是組成類的一部分。方法有名字、類型簽名,有時方法上還有注解,以及方法的功能實現(xiàn)代碼(字節(jié)碼)。

Scala 中的函數(shù)是一個完整的對象。Scala 中用 22 個特質(trait)抽象出了函數(shù)的概念。這 22 特質從 Function1 到 Function22:

Scala 方法和函數(shù)的區(qū)別是什么

如上圖中的 Function10 代表的是:有 10 個形參,返回值為 R(協(xié)變)的函數(shù)。

函數(shù)更常使用的是匿名函數(shù),定義的時候只需要說明輸入?yún)?shù)的類型和函數(shù)體即可,不需要名稱如果你要是用的話,一般會把這個匿名函數(shù)賦值給一個變量(其實是val常量) 
 表現(xiàn)形式:(傳入?yún)?shù))=>{方法體}

val f = (name:String)=>println("Hi,"+name)
 f("kafka")

Scala 中的函數(shù)其實就是繼承了這些 Trait 的類的對象,如:我們通過函數(shù)字面量定義一個函數(shù)

Scala 方法和函數(shù)的區(qū)別是什么

 其實上述函數(shù)的定義方式跟如下定義方式等同:

Scala 方法和函數(shù)的區(qū)別是什么

由于 Function2 是特質,不能直接 new。上述 new Function2[Int,Int,Int](){} 其實是定義并實例化一個實現(xiàn)了 Function2 特質的類的對象。

apply 是 scala 中的語法糖:對一個對象 obj 上調用 obj(),scala 編譯器會轉換為 obj.apply();在一個類 clazz 上調 clazz(),scala 編譯器會轉換為 clazz_company_obj.apply(),其中 clazz_company_obj 為 clazz 的伴生對象。

具體的差異,總結為如下幾點:

1. 方法不能作為單獨的表達式而存在(參數(shù)為空的方法除外),而函數(shù)可以。如:

scala> def m(x:Int) = 2.0*x
m: (x: Int)Double   方法的定義

scala> val f = (x:Int)=> 2.0*x 
f: Int => Double = <function1>  函數(shù)定義

scala> f
res7: Int => Double = <function1> 函數(shù)就是

scala> val tmp = m _  通過這個方式還可以實現(xiàn)方法到函數(shù)的變化
tmp: Int => Double = <function1>

scala> m  直接調用方法名是錯誤的
<console>:13: error: missing argument list for method m
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `m _` or `m(_)` instead of `m`.
       m
       ^

在Scala語言中, 函數(shù)也是對象, 每一個對象都是scala.FunctionN(1-22)的實例, 其中N是函數(shù)參數(shù)的數(shù)量, 例如我們定義一個函數(shù)并復制給一個變量:

scala> val f = (x: Int) => x + 1 (匿名函數(shù)的寫法)
f: Int => Int = <function1>
 這里定義了一個接收一個整型變量作為參數(shù)的函數(shù), 函數(shù)的功能是返回輸入?yún)?shù)加1. 可以看到REPL返回參數(shù)的toString方法 即 <function0> . 
 那么如果我們有一個指向函數(shù)對象的引用, 我們該如何調用這個函數(shù)呢? 答案是通過FunctionN的 apply 方法, 即 FunctionN.apply() , 因此調用函數(shù)對象的方法如下: 

scala> f.apply(3)
res2: Int = 4
但是如果每次調用方法對象都要通過FunctionN.apply(x, y...), 就會略顯啰嗦, Scala提供一種模仿函數(shù)調用的格式來調用函數(shù)對象

scala> f(3)
res3: Int = 4

在如上的例子中,我們首先定義了一個方法 m,接著有定義了一個函數(shù)f。接著我們把函數(shù)名(函數(shù)值)當作最終表達式來用,由于f本身就是一個對象(實現(xiàn)了 FunctionN 特質的對象),所以這種使用方式是完全正確的。但是我們把方法名當成最終表達式來使用的話,就會出錯。

2.方法可以沒有參數(shù)列表而 函數(shù)必須要有參數(shù)列表

scala> def m1 = 100
m1: Int 沒有入?yún)⒌姆椒ǘx 是下面的簡寫形式

scala> def m2() = 100
m2: ()Int 無入?yún)⒌姆诺蕉x

scala> val f1 = ()=>100  無入?yún)⒌暮瘮?shù)定義
f1: () => Int = <function0>

scala> val f1 = => 100  仿照最上面寫就直接報錯
<console>:1: error: illegal start of simple expression
val f1 = => 100

在如上的例子中,m1方法接受零個參數(shù),所以可以省略參數(shù)列表。而函數(shù)不能省略參數(shù)列表。

3.方法名是方法調用,而函數(shù)名只是代表函數(shù)對象本身

這個比較容易理解。因為保存函數(shù)字面量的變量(又稱為函數(shù)名或者函數(shù)值)本身就是實現(xiàn)了 FunctionN 特質的類的對象,要調用對象的 apply方法,就需要使用obj()的語法。所以函數(shù)名后面加括號才是調用函數(shù)。如下:

scala> def m1 = 100
m1: Int 方法定義

scala> val f1 = ()=> 100 函數(shù)定義
f1: () => Int = <function0>

scala> m1 方法調用
res11: Int = 100

scala> f1 函數(shù)查看
res12: () => Int = <function0>

scala> f1() 函數(shù)調用,是下面調用方式的簡單版
res13: Int = 100

scala> f1.apply() 函數(shù)調用的正確形式
res14: Int = 100

4.在需要函數(shù)的地方,如果傳遞一個方法,會自動進行ETA展開(把方法轉換為函數(shù))

Scala 方法和函數(shù)的區(qū)別是什么

如上,如果我們直接把一個方法賦值給變量會報錯。如果我們指定變量的類型就是函數(shù),那么就可以通過編譯,如下:

scala> val f1:(Int)=>Int = m
f1: Int => Int = <function1>

當然我們也可以強制把一個方法轉換給函數(shù),這就用到了 scala 中的部分應用函數(shù):

scala> val f1 = m _ 
f1: Int => Int = <function1>

scala> val f1 = m(_)
f1: Int => Int = <function1>

5.傳名參數(shù)本質上是個方法

傳名參數(shù)實質上是一個參數(shù)列表為空的方法,因為函數(shù)的話參數(shù)列表是不能為空的!(區(qū)別2參考),如下:

scala> def m1(x: =>Int) = List(x,x)
m1: (x: => Int)List[Int]

如上代碼實際上定義了一個方法 m1,m1 的參數(shù)是個傳名參數(shù)(方法)。由于對于參數(shù)為空的方法來說,方法名就是方法調用 ,所以List(x,x)實際上是進行了兩次方法調用。

Scala 方法和函數(shù)的區(qū)別是什么

由于 List(x,x) 是進行了兩次方法調用,所以得到兩個不同的值。如果我們稍微修改一下函數(shù)的m1的定義,把x先緩存起來,結果就會跟以前大不一樣。

scala> def m1(x: => Int) = {val y = x;List(y,y)}
m1: (x: => Int)List[Int]

scala> m1(r.nextInt)
res18: List[Int] = List(-723271792, -723271792)

6. 方法跟函數(shù)當參數(shù)的調用

    // 方法定義
    def method1(arge1: Int, arge2: Int) = arge1 + arge2

    // 函數(shù)定義
    val funct1 = (arge1: Int, arge2: Int) => arge1 - arge2

    def method2(f: (Int, Int) => Int) = f(12, 12)

    println("方法傳方法" + method2(method1))
    
    val funct2 = (f: (Int, Int) => Int) => f(22, 22)
    println("函數(shù)傳方法" + funct2(method1))
    
    def method3(f: (Int, Int) => Int) = f(4, 1)
    println("方法傳函數(shù)" + method3(funct1))

    val funct3 = (f: (Int, Int) => Int) => f(5, 1)
    println("函數(shù)傳函數(shù)" + funct3(funct1))

--------------------------------------------------------------------------------------

    //  調用方式一 方法調用方法
    def method1(): Unit = println("printmethod1")

    def method2(m: () => Unit): Unit = m() // 如果參數(shù)列表寫的是帶()  調用的時候也要帶()


    method2(method1) //執(zhí)行

    // 調用方式二 方法調用方法
    def method11: Unit = println("printmethod11")

    def method22(m: => Unit) = m // 如果參數(shù)列表中 就沒有() 此處不可寫m()

    method22(method11) //執(zhí)行

    //調用方式三
    def method111(): Unit = println("printmethod111")

    def method222(m: () => Unit) = m // 如果參數(shù)列表帶()  調用時候不帶(),則不會執(zhí)行

    method222(method111) //此處沒有輸出

Scala 中Apply講解

class ApplyTest{
  def apply() = println("I am into Spark so much!!!")
   
  def haveATry{
    println("Have a try on apply!")
  }
}
object ApplyTest{
  def apply() = {
    println("I am into Scala so much!!!")
    new ApplyTest
  }
}
object ApplyOperation {
  def main(args: Array[String]) {
    val array = Array(1,2,3,4,5)
    val a = ApplyTest() //這里并沒有new,然后確實返回了類的實例
    a.haveATry 
  }
}

輸出結果:

I am into Scala so much!!!
Have a try on apply!

在一個類的伴生對象里面,實現(xiàn)apply方法,在這里面可以創(chuàng)建類的實例。譬如val a = Array(1, 2, 3)就是使用了Array的apply方法。

同樣,在class里面也可以使用apply方法:

object ApplyOperation {
  def main(args: Array[String]) {
     val a = new ApplyTest
     a.haveATry
     println(a())  //調用class的apply方法
  }
}

結果:

Have a try on apply!
I am into Spark so much!!!
()

上述就是小編為大家分享的Scala 方法和函數(shù)的區(qū)別是什么了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

文章標題:Scala方法和函數(shù)的區(qū)別是什么
URL標題:http://jinyejixie.com/article24/pgspje.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、品牌網(wǎng)站制作、營銷型網(wǎng)站建設、電子商務、網(wǎng)站設計、網(wǎng)頁設計公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

微信小程序開發(fā)
桐乡市| 聂荣县| 额敏县| 大悟县| 道真| 桃园县| 东城区| 韩城市| 锦屏县| 长丰县| 敦化市| 谢通门县| 澄迈县| 尤溪县| 桦甸市| 昌都县| 黎城县| 梁平县| 新闻| 衡东县| 城固县| 汝阳县| 潞西市| 都安| 新巴尔虎左旗| 西青区| 张家港市| 永州市| 十堰市| 濮阳县| 揭西县| 楚雄市| 雅江县| 色达县| 铅山县| 建宁县| 扬中市| 呼图壁县| 波密县| 万安县| 高邑县|