Scala:(四) 方法、函式、Trait
scala中既有函式也有方法,在大多數情況下,不用理會其區別也可正常使用。但有時候還是要區分其異同。
Scala 有方法與函式,二者在語義上的區別很小。Scala 方法是類的一部分,而函式是一個物件可以賦值給一個變數。換句話來說在類中定義的函式即是方法。
有些翻譯上函式(function)與方法(method)是沒有區別的。在寫這篇部落格的過程中,也參考了一些資料,但大都不能令我滿意。所以,知道即可,不要過於追究這勞什子,scala是一門語言,語言自然以使用為第一要務。
方法
Scala中的方法跟Java的方法一樣,方法是組成類的一部分。方法有名字、型別簽名,有時方法上還有註解,以及方法的功能實現程式碼(位元組碼)
我們來定義看一個最經典的方法
函式
再來定義一個函式
其主要區別為:
在函數語言程式設計語言中,函式是“頭等公民”,它可以像任何其他資料型別一樣被傳遞和操作
函式定義語法 用def來定義
可以定義傳入的引數,要指定傳入引數的型別
方法可以寫返回值的型別也可以不寫,會自動推斷,有時候不能省略,必須寫,比如在遞迴函式中或者函式的返回值是函式型別的時候。
scala中函式有返回值時,可以寫return,也可以不寫return,會把函式中最後一行當做結果返回。當寫return時,必須要寫函式的返回值。
如果返回值可以一行搞定,可以將{}省略不寫
傳遞給方法的引數可以在方法中使用,並且scala規定方法的傳過來的引數為val的,不是var的。
如果去掉方法體前面的等號,那麼這個方法返回型別必定是Unit的。這種說法無論方法體裡面什麼邏輯都成立,scala可以把任意型別轉換為Unit.假設,裡面的邏輯最後返回了一個string,那麼這個返回值會被轉換成Unit,並且值會被丟棄。
函式也可作為引數傳遞到方法裡
方法也可轉為函式
方法及函式的呼叫
基本使用與java也類似。同樣可以點出來,各種操作符也是可以使用的。
Scala中的+ - * / %等操作符的作用與Java一樣,位操作符 & | ^ >> <<也一樣。只是有一點特別的:這些操作符實際上是方法。
a + b
是如下方法呼叫的簡寫:
a.+(b)
a 方法 b可以寫成 a.方法(b)
遞迴函式
注:遞迴函式的返回值是必須寫的
/** * 遞迴函式 * 5的階乘 */ def fun2(num :Int) :Int= { if(num == 1) num else num * fun2(num-1) //將函式也作為返回值,直到 num==1 } print(fun2(5))
引數預設值及可變形參
scala與java類似,引數同樣可以有預設值,且引數個數也可以是不定的
預設值的函式中,如果傳入的引數個數與函式定義相同,則傳入的數值會覆蓋預設值。
如果不想覆蓋預設值,傳入的引數個數小於定義的函式的引數,則需要指定引數名稱。
def fun3(a :Int = 10,b:Int) = {
println(a+b)
}
fun3(b=2)
對於引數不定的,引數之間要用逗號隔開
def fun4(elements :Int*)={
var sum = 0;
for(elem <- elements){
sum += elem
}
sum
}
println(fun4(1,2,3,4))
Trait
Scala Trait(特徵) 相當於 Java 的介面,實際上它比介面還功能強大。與介面不同的是,它還可以定義屬性和方法的實現。
這裡的trait字面意思是特質或者特徵,這個詞翻譯成特徵比較合適。它的意義和java,c#中介面很類似。但是trait支援部分實現,也就是說可以在scala的trait中可以實現部分方法。
一般情況下Scala的類可以繼承多個Trait,從結果來看就是實現了多重繼承。Trait(特徵) 定義的方式與類類似,但它使用的關鍵字是 trait。
繼承的多個trait中如果有同名的方法和屬性,必須要在類中使用“override”重新定義。
trait中不可以傳引數
trait Read {
val readType = "Read"
val gender = "m"
def read(name:String){
println(name+" is reading")
}
}
trait Listen {
val listenType = "Listen"
val gender = "m"
def listen(name:String){
println(name + " is listenning")
}
}
class Person() extends Read with Listen{
override val gender = "f"
}
object test {
def main(args: Array[String]): Unit = {
val person = new Person()
person.read("zhangsan")
person.listen("lisi")
println(person.listenType)
println(person.readType)
println(person.gender)
}
}
一下引用菜鳥教程的部分內容,原文摘錄:
/* 檔名:Test.scala
* author:菜鳥教程
* url:www.runoob.com
*/
trait Equal {
def isEqual(x: Any): Boolean
def isNotEqual(x: Any): Boolean = !isEqual(x)
}
class Point(xc: Int, yc: Int) extends Equal {
var x: Int = xc
var y: Int = yc
def isEqual(obj: Any) =
obj.isInstanceOf[Point] &&
obj.asInstanceOf[Point].x == x
}
object Test {
def main(args: Array[String]) {
val p1 = new Point(2, 3)
val p2 = new Point(2, 4)
val p3 = new Point(3, 3)
println(p1.isNotEqual(p2))
println(p1.isNotEqual(p3))
println(p1.isNotEqual(2))
}
}
執行結果為:
false
true
true