一、scala語言有什么特點?什么是函數式編程?有什么優點?
1、scala語言集成面向對象和函數式編程
2、函數式編程是一種典范,將電腦的運算視作是函數的運算。
3、與過程化編程相比,函數式編程里的函數計算可以隨時調用。
4、函數式編程中,函數是一等功明。
二、scala中的閉包
1、定義:你可以在任何作用域內定義函數:包,類甚至是另一個函數或方法。在函數體內,可以訪問到相應作用域內地任何變量。(重點)函數可以在變量不再處於作用域內時被調用。
例如:
def mulBy(factor:Double) = (x:Double) => factor * x
//開始調用
val tripe = mulBy(3)
val half = mulBy(0.5)
println(tripe(14) + " " + half(14))
這就是一個閉包
三、scala中的柯里化
定義:柯里化指的是將原來接受兩個參數的函數變成新的接受一個參數的函數的過程。新的函數返回一個以原有的第二個參數作為參數的函數
例如:
def mul(x:Int,y:Int) = x * y //該函數接受兩個參數
def mulOneAtTime(x:Int) = (y:Int) => x * y //該函數接受一個參數生成另外一個接受單個參數的函數
這樣的話,如果需要計算兩個數的乘積的話只需要調用:
mulOneAtTime(5)(4)
這就是函數的柯里化
四、scala中的模式匹配
scala的模式匹配包括了一系列的備選項,每個替代項以關鍵字大小寫為單位,每個替代方案包括一個模式或多個表達式,如果匹配將會進行計算,箭頭符號=>將模式與表達式分離
例如:
obj match{
case 1 => "one"
case 2 => "two"
case 3 => "three"
case _ => default
}
五、case class和class的區別
case class:
是一個樣本類,樣本類是一種不可變切可分解類的語法糖,也就是說在構建的時候會自動生成一些語法糖,具有以下幾個特點:
1、自動添加與類名一致的構造函數(也就是半生對象,通過apply方法實現),也就是說在構造對象的時候不需要使用new關鍵字
2、樣本類中的參數默認是val關鍵字,不可以修改
3、默認實現了toString,equals,hashcode,copy方法
4、樣本類可以通過==來比較兩個對象,不在構造方法內地二屬性不會用在比較上
class:
class是一個類
1、class在構造對象的時候需要使用new關鍵字才可以。
六、談談scala中的隱式轉換
所謂的隱式轉換函數(implicit conversion function)指的事那種以implicit關鍵字申明的帶有單個參數的函數,這樣的函數會被自動的應用,將值從一種類型轉換為另一種類型
比如:需要把整數n轉換成分數n/1
implicit def int2Fraction(n:Int) = Fraction(n,1)
這樣就可以做如下表達式求職:
val result = 3 * Fraction(4,5)
此時,隱士轉換函數將整數3轉換成一個Fraction對象,這個對象接着又被乘以Fraction(4,5)
七、scala中的伴生類和伴生對象是怎么一回事
在scala中,單例對象與類同名時,該對象被稱為該類的伴生對象,該類被稱為該對象的伴生類。
伴生類和伴生對象要處在同一個源文件中
伴生對象和伴生類可以互相訪問其私有成員
不與伴生類同名的對象稱之為孤立對象
八、scala和java 的區別
1、變量申明:
scala:只需要申明是val或是var,具體的類型(比如String,Int,Double等等),由編譯器自行推斷
java: 需要在變量前面先注明變量的類型
2、返回值:
scala:申明返回值是在后面,並且不需要return語句,非要用,也不是不可以
java: 如果有返回值,需要return語句
3、結束符
scala:不需要使用分號作為結束符
java: 每個語句結束后需要分號作為結束符
4、循環
scala:循環語句可以用於守衛
java: 不可以這么寫
5、通配符:
scala:_
java: *
6、構造器
scala:構造器名稱為this,scala的輔助構造器之前需要有一個主構造器或者其他輔助構造器,並且scala的構造器參數可以直接放在類的后面
java: 構造器名稱需要與類名稱一樣
7、內部類
scala:scala實例化的內部類是不同的,可以使用類型投影,例如 Network#Person表示Network的Person類
java:內部類從屬於外部類
8、接口
scala:scala中接口稱為特質(trait),特質中是可以寫抽象方法,也可以寫具體的方法體以及狀態。且類是可以實現多個特質的。
特質中未被實現的方法默認就是抽象的
子類的實現或繼承統一使用的事extends關鍵字,如果需要實現或繼承多個使用with關鍵字
特質中可以有構造器
特質可以繼承普通的類,並且這個類稱為所有繼承trait的父類
java: java中的接口(interface),接口中的方法只能是抽象方法,不可以寫具體包含方法體的方法
接口中不能有抽象的屬性,且屬性的修飾符都是public static final
類實現接口需要使用implements關鍵字,實現多個接口,需要用逗號隔開
接口中不可以有構造器
接口不可以繼承普通的類
9、賦值
scala:scala中的賦值語句返回結果是unit的不可以串聯,例如x=y=1,這樣是有問題的,x並沒有被賦值為1
java: x=y=1,這樣是沒問題的
九、談談scala的尾遞歸
正常得遞歸,每一次遞歸步驟,需要保存信息到堆棧中去,當遞歸步驟很多的時候,就會導致內存溢出
而尾遞歸,就是為了解決上述的問題,在尾遞歸中所有的計算都是在遞歸之前調用,編譯器可以利用這個屬性避免堆棧錯誤,尾遞歸的調用可以使信息不插入堆棧,從而優化尾遞歸
例如:
正常遞歸:
def sum(n:Int):Int = {
if (n == 0){
n
}else{
n + sum(n - 1)
}
}
//執行結果
sum(5)
5 + sum(4) // 暫停計算 => 需要添加信息到堆棧 5 + (4 + sum(3)) 5 + (4 + (3 + sum(2))) 5 + (4 + (3 + (2 + sum(1)))) 5 + (4 + (3 + (2 + 1))) 15
尾遞歸
@tailrec //告訴編譯器,強制使用尾遞歸
def tailSum(n:Int,acc:Int = 0):Int = {
if (n ==0 ){
acc
}else{
tailSum(n - 1,acc + n)
}
}
//執行結果
tailSum(5) // tailSum(5, 0) 默認值是0
tailSum(4, 5) // 不需要暫停計算 tailSum(3, 9) tailSum(2, 12) tailSum(1, 14) tailSum(0, 15) 15