在我沒有學(xué)習(xí) scala 的時(shí)候,主要用 java 和 python 做日常工作開發(fā),印象中,沒有特別的刻意的去區(qū)分 method 和 function 的區(qū)別,這個(gè)關(guān)系,正如我們?nèi)粘I钪?,沒有刻意的去區(qū)分質(zhì)量和重量。但是,他們之間,的確是有所不同的,這些不同也是建立在他們之間有聯(lián)系的基礎(chǔ)之上!
如何定義
首先,還是引用英文原文來看看他們?cè)诙x上的區(qū)別和聯(lián)系吧:
A Function Type is (roughly) a type of the form (T1, …, Tn) => U, which is a shorthand for the trait FunctionN
in the standard library. Anonymous Functions and Method Values have function types, and function types can be used as part of value, variable and function declarations and definitions. In fact, it can be part of a method type.
A Method Type is a non-value type. That means there is no value – no object, no instance – with a method type. As mentioned above, a Method Value actually has a Function Type. A method type is a def
declaration – everything about a def
except its body.
例子:
scala> def m1(x:Int) = x+3 m1: (x: Int)Int scala> val f1 = (x: Int) => x+3 f1: Int => Int = <function1>
看到?jīng)],方法定義和函數(shù)定義是不是在scala的解析器signature上就有顯示了,def m1(x: Int) = x+3就是一個(gè)簡單的method的定義。signature中m1: (x: Int)Int 表示method m1有一個(gè)參數(shù)Int型參數(shù)x,返回值是Int型。
val f1 = (x: Int) => x+3則是function的定義,解析器的signature中f1: Int => Int = <function1>表示function f1的method體接受一個(gè)Int型的參數(shù),輸出結(jié)果的類型是Int型。
從上面的例子,得出一個(gè)總結(jié):
方法是一個(gè)以def開頭的帶有參數(shù)列表(可以無參數(shù)列表)的一個(gè)邏輯操作塊,這正如object或者class中的成員方法一樣。
函數(shù)是一個(gè)賦值給一個(gè)變量(或者常量)的匿名方法(帶或者不帶參數(shù)列表),并且通過=>轉(zhuǎn)換符號(hào)跟上邏輯代碼塊的一個(gè)表達(dá)式。=>轉(zhuǎn)換符號(hào)后面的邏輯代碼塊的寫法與method的body部分相同。
其他區(qū)別
method 可以作為一個(gè)表達(dá)式的一部分出現(xiàn)(調(diào)用函數(shù)并傳參),但是 method(帶參方法)不能作為最終的表達(dá)式(無參方法可以,但是這個(gè)就成了方法調(diào)用,因?yàn)?scala 允許無參方法調(diào)用時(shí)省略()括號(hào)),而 function 可以作為最終的表達(dá)式出現(xiàn)。
scala> m1 <console>:12: error: missing arguments for method m1; follow this method with `_' if you want to treat it as a partially applied function m1 ^ scala> f1 res1: Int => Int = <function1>
method 可以沒有參數(shù)列表,參數(shù)列表也可以為空。但是 function 必須有參數(shù)列表(也可以為空)。方法名意味著方法調(diào)用,函數(shù)名只是代表函數(shù)自身:
scala> def m2 = 100; m2: Int scala> def m3() = 1000; m3: ()Int scala> var f2 = => 100; <console>:1: error: illegal start of simple expression var f2 = => 100; ^ scala> var f2 =()=> 100; f2: () => Int = <function0> scala> m2 res2: Int = 100 scala> m3 res3: Int = 1000 scala> m3() res4: Int = 1000 scala> f2 res5: () => Int = <function0> scala> f2() res6: Int = 100
在函數(shù)出現(xiàn)的地方我們可以提供一個(gè)方法。
這是因?yàn)椋绻谕霈F(xiàn)函數(shù)的地方我們提供了一個(gè)方法的話,該方法就會(huì)自動(dòng)被轉(zhuǎn)換成函數(shù)。該行為被稱為 ETA expansion。
注意:
期望出現(xiàn)函數(shù)的地方,我們可以使用方法。
不期望出現(xiàn)函數(shù)的地方,方法并不會(huì)自動(dòng)轉(zhuǎn)換成函數(shù)。
在 scala 中操作符被解釋稱方法:
- 前綴操作符:op obj 被解釋稱 obj.op
- 中綴操作符:obj1 op obj2 被解釋稱 obj1.op(obj2)
- 后綴操作符:obj op 被解釋稱 obj.op
scala> val ml = List(1,2,3,4) ml: List[Int] = List(1, 2, 3, 4) scala> ml.map((x)=>2*x) res0: List[Int] = List(2, 4, 6, 8) scala> def m(x:Int) = 2*x m: (x: Int)Int scala> ml.map(m) res1: List[Int] = List(2, 4, 6, 8) scala> def m(x:Int) = 3*x m: (x: Int)Int scala> ml.map(m) res2: List[Int] = List(3, 6, 9, 12)
可以在方法名后面加一個(gè)下劃線強(qiáng)制變成函數(shù)。
注意: 方法名與下劃線之間至少有一個(gè)空格喲!
scala> def m3(x: Int): Int = x * x * x m3: (x: Int)Int scala> val f3 = m3_ <console>:10: error: not found: value m3_ val f3 = m3_ ^ scala> val f3 = m3 _ f3: Int => Int = <function1> scala> f3(3) res0: Int = 27
原文地址:https://www.cnblogs.com/shihuc/p/5082701.html