回答
方法和函數之間的一個很大的實際區別是return
的含義。 return
只能從方法返回。例如:
scala> val f =() => { return "test" }
<console>:4: error: return outside method definition
val f =() => { return "test" }
^
在方法定義的函數返回不非本地回報:
scala> def f: String = {
| val g =() => { return "test" }
| g()
| "not this"
| }
f: String
scala> f
res4: String = test
而從本地方法只從方法返回返回。
scala> def f2: String = {
| def g(): String = { return "test" }
| g()
| "is this"
| }
f2: String
scala> f2
res5: String = is this
吉姆已經得到了這個幾乎涵蓋在his blog post,但我在這裏張貼的簡報以供參考。
首先,讓我們看看Scala規範告訴我們什麼。第3章(類型)告訴我們有關函數類型(3.2.9)和方法類型(3.3.1)。第4章(基本聲明)說到Value Declaration and Definitions(4.1),變量聲明和定義(4.2)和函數聲明和定義(4.6)。第6章(表達式)說明匿名函數(6.23)和方法值(6.7)。奇怪的是,函數值在3.2.9上被說了一次,而沒有其他地方。
甲功能類型是(大約)類型的形式(T1,...,TN)=>ü,這是在標準庫性狀FunctionN
的簡寫的。 匿名函數和方法值具有函數類型,函數類型可用作值,變量和函數聲明和定義的一部分。實際上,它可以是方法類型的一部分。
甲方法類型是非值類型。這意味着有否值 - 沒有對象,沒有實例 - 帶有方法類型。如上所述,方法值實際上有一個功能類型。方法類型是def
聲明 - 除了它的主體外,關於def
的所有內容。
值聲明和定義和變量聲明和定義是val
和var
聲明,包括類型和值兩者 - 其可以是分別功能類型和匿名函數或方法值。請注意,在JVM上,這些(方法值)是用Java調用「方法」的方式實現的。
甲函數聲明是def
聲明,包括類型和體。類型部分是方法類型,正文是表達式或塊。這也通過Java調用「方法」的方式在JVM上實現。
最後,匿名函數是的功能類型一個實例(即特徵FunctionN
的實例),和方法值是一樣的東西!區別在於通過後綴固定下劃線(m _
是對應於「函數聲明」(def
)m
)的方法值或通過稱爲eta-expansion的過程來創建方法值,方法類似於從方法到功能的自動轉換。
這就是規格說明,所以讓我把這個預先的:我們不使用那個術語!它導致所謂的「函數聲明」(它是程序的一部分(第4章 - 基本聲明)和「匿名函數」,它是一個表達式,和「函數鍵入「,這是一種類型 - 一種特質。
下面的術語,由經驗豐富的程序員斯卡拉使用,使得從規範的術語一個變化:而不是說函數聲明,我們說方法。甚至方法聲明。此外,我們注意到價值聲明和變量聲明也是實際用途的方法。
因此,鑑於上述術語的變化,下面是對這種區別的實際解釋。
甲功能是一個對象,它包括FunctionX
特徵之一,如Function0
,Function1
,Function2
等,這可能包括PartialFunction
爲好,這實際上延伸Function1
。
讓我們來看看類型簽名的這些特徵之一:
trait Function2[-T1, -T2, +R] extends AnyRef
這個特點有一個抽象方法(它有一些具體方法爲好):
def apply(v1: T1, v2: T2): R
這告訴我們所有關於它的知識。甲函數具有接收的類型T1,T2,...,TN Ñ參數的apply
方法,並返回R
類型的東西。它在接收到的參數上是相反的變體,並且結果是共變的。
該差異意味着Function1[Seq[T], String]
是Function1[List[T], AnyRef]
的子類型。作爲子類型意味着它可以用代替它。人們可以很容易地看到,如果我打電話給f(List(1, 2, 3))
,並期望返回AnyRef
,則上述兩種類型中的任何一種都可以工作。
現在,什麼是相似度的方法和函數?好吧,如果f
是一個功能和m
是本地的範圍方法,然後既可以這樣調用:
val o1 = f(List(1, 2, 3))
val o2 = m(List(1, 2, 3))
這些電話實際上是不同的,因爲第一個只是一個語法糖。斯卡拉擴大它到:
val o1 = f.apply(List(1, 2, 3))
當然,這是一個方法調用對象f
。函數還具有其他語法糖類:函數文字(其中兩個,實際上)和(T1, T2) => R
類型簽名。例如:
val f = (l: List[Int]) => l mkString ""
val g: (AnyVal) => String = {
case i: Int => "Int"
case d: Double => "Double"
case o => "Other"
}
的方法和功能之間的另一個相似的是,前者可以容易地轉換成後者:
val f = m _
的Scala將擴大該,假設m
類型是(List[Int])AnyRef
成(Scala 2.7):
val f = new AnyRef with Function1[List[Int], AnyRef] {
def apply(x$1: List[Int]) = this.m(x$1)
}
在Scala 2.8上,它實際上使用了一個AbstractFunction1
cl屁股,以減少班級人數。
請注意,無法將其他方式轉換 - 從函數轉換爲方法。然而,方法有一個很大的優點(好,兩個 - 它們可以稍微快一些):它們可以接收類型參數。例如,儘管上述f
未必能夠指定的List
接收(List[Int]
中的例子)的類型,m
可以將其參數化:
def m[T](l: List[T]): String = l mkString ""
我認爲這幾乎涵蓋了一切,但我會很高興來補充這可以解答任何可能存在的問題。
這個解釋非常清楚。做得好。 不幸的是,Odersky/Venners/Spoon書籍和Scala規範都有些可以互換地使用「功能」和「方法」兩個詞。 (他們可能會說「功能」,其中「方法」會更清楚,但有時也會發生另一種方式,例如,規範的第6.7節將涵蓋了將方法轉換爲函數的方法,稱爲「方法值」。 ) 我認爲,當人們嘗試學習這門語言時,這些詞的鬆散使用導致了很多混亂。 –
@我知道,我知道 - PinS是教我Scala的書。我更好地學習了困難的方法,也就是說,帕普讓我直說。 –
很好的解釋!我有一件事要補充:當你引用編譯器的'val f = m'擴展爲'val f = new Function'[List [Int],AnyRef] def apply(x $ 1:List [Int ')= this.m(x $ 1) }''你應該指出'apply'方法中的'this'並不是指向AnyRef對象,而是指向valf =因爲'this'是由閉包捕獲的值(例如,如下面指出的'return'),因此m_'被評估(_outer_'this',可以這麼說)。 –
比方說您有一個List
scala> val x =List.range(10,20)
x: List[Int] = List(10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
定義一個方法
scala> def m1(i:Int)=i+2
m1: (i: Int)Int
定義一個函數
scala> (i:Int)=>i+2
res0: Int => Int = <function1>
scala> x.map((x)=>x+2)
res2: List[Int] = List(12, 13, 14, 15, 16, 17, 18, 19, 20, 21)
方法接受參數
scala> m1(2)
res3: Int = 4
定義功能的VAL
scala> val p =(i:Int)=>i+2
p: Int => Int = <function1>
參數,以功能爲選配
scala> p(2)
res4: Int = 4
scala> p
res5: Int => Int = <function1>
參數的方法是強制性
scala> m1
<console>:9: error: missing arguments for method m1;
follow this method with `_' if you want to treat it as a partially applied function
檢查以下Tutorial,說明通過其他方面的差異有類似的例子使用方法Vs函數的其他差異示例,使用函數作爲變量,創建函數即返回功能
功能 N的函數可以使用的參數列表產生 結果被調用。一個函數有一個參數列表,一個主體和一個結果類型。 屬於類,特徵或單例對象成員的函數是 ,稱爲方法。在其他功能中定義的功能稱爲 本地功能。結果類型爲Unit的函數稱爲過程。 源代碼中的匿名函數稱爲函數文字。 在運行時,函數文字被實例化爲對象,稱爲 函數值。
Programming in Scala Second Edition. Martin Odersky - Lex Spoon - Bill Venners
函數可以作爲def或val/var屬於一個類。只有def是方法。 –
有一個很好的文章here從我的大部分描述都採取。 只是關於我的理解功能和方法的簡短比較。希望它有幫助:
函數: 它們基本上是一個對象。更確切地說,函數是具有應用方法的對象;因此,由於它們的開銷,它們比方法稍慢。它與靜態方法類似,它們獨立於要調用的對象。 功能的一個簡單的例子是一樣波紋管:
val f1 = (x: Int) => x + x
f1(2) // 4
上面的線是除了像object1 = Object2的分配一個對象到另一什麼。實際上,在我們的例子中,object2是一個匿名函數,因此左側獲得了一個對象的類型。因此,現在f1是一個對象(Function)。匿名函數實際上是Function1 [Int,Int]的一個實例,它表示一個函數,其中1個參數的類型爲Int,返回值的類型爲Int。 無參數調用F1會給我們的匿名函數(INT => INT =)
方法的簽名: 他們不是對象,但分配到一個類的實例,即,一個對象。完全一樣的,在C++中的java或成員函數(如Raffi Khatchadourian在註釋中指出到this question)方法等 的方法的一個簡單的例子是一樣波紋管:
def m1(x: Int) = x + x
m1(2) // 4
上面的線是不一個簡單的值賦值,但是一個方法的定義。當你像第二行一樣調用這個值爲2的方法時,x被替換爲2並且結果將被計算並且你得到4作爲輸出。在這裏你會得到一個錯誤,如果只是簡單地寫m1,因爲它是方法並且需要輸入值。通過使用_你可以將方法分配給一個函數像波紋管:
val f2 = m1 _ // Int => Int = <function1>
- 1. 功能和方法的區別
- 2. 功能VS Scala的方法
- 3. Scala中&和&&的區別?
- 4. Scala Iterable和IterableLike的區別和用法
- 5. Sharepoint 2007和2010中功能的區別
- 6. scala中的別名方法?
- 7. 區別對象和功能
- 8. 稱取功能Scala的泛型方法
- 9. Scala和Java中的RoundingMode.HALF_UP區別
- 10. 方法覆蓋和功能覆蓋/超載有什麼區別
- 11. 功能與新功能的JavaScript區別
- 12. JSON中.put()和.element()方法的區別?
- 13. java中addItem和insertItemAt方法的區別
- 14. iphone中的區塊和功能有什麼區別
- 15. Scala的類型層級識別功能
- 16. 「功能」和「功能!」有什麼區別?在VIM中?
- 17. 功能Scala的
- 18. Scala:方法參數String *和Array [String]之間是否有區別
- 19. 的iOS:方法和功能
- 20. 成功和$ .ajax的.done()方法之間有什麼區別
- 21. scala和java枚舉之間的區別
- 22. Anorm Scala executeUpdate和executeInsert之間的區別
- 23. scala地圖和flatMap的區別
- 24. Javascript:$(function(){});有什麼區別?和功能(){}
- 25. Scala類型別名和方法重載
- 26. SecKeychainAddGenericPassword中的serviceName和accountName之間的功能區別
- 27. Python中的string方法和str方法有什麼區別?
- 28. Get方法和Set方法在類中的區別
- 29. 函數方法和分類方法在reactjs中的區別
- 30. 在Scala中分組實用程序功能的首選方法?
http://jim-mcbeath.blogspot.com/2009/05/scala-functions-vs-methods.html –
我想你可以從[方法和函數之間的區別是什麼]得到一些東西(http://stackoverflow.com/questions/155609/what-is-the-difference-between-a-method-and-a-function) – jinglining
A後續問題與良好的答案:[函數與斯卡拉方法](http://stackoverflow.com/questions/4839537/functions-vs-methods-in-scala) –